HylaFAX The world's most advanced open source fax server

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]

[hylafax-users] [RECIPE] Pretty SVG-based server-side cover page generation with HylaFAX+



Current HylaFAX+ has support for using the server's continuation cover
page generation for a job's initial cover page. I've used this together
with the Genshi XML templating language and Inkscape's command-line
SVG-to-PDF rendering mode to make some reasonably pretty cover pages -- and with much less hassle than is involved in templatizing PDF documents. (Yaay, GUI tools!)


I'm presenting this here rather than on the hylafax+ list because folks
looking for easier ways to generate cover page templates are prone to
looking here first, and the technique could be adopted to client-side cover page generation and thus used with the hylafax.org tree, or used only for continuation cover page generation with initial cover pages continuing to be created client-side.


Because XML files marked up with Genshi are still valid XML files
readable in the application that created them, the SVG file to be used
as a template can be created with Inkscape in its regular GUI mode; just
use ${FOO} inside text fields to substitute in any exported environment
variables, or use Genshi attributes such as py:if, py:for,
py:replace, py:content, and the like for fancier templating. Python
statements can also be used; for instance, ${int(QFILE_npages) +
int(QFILE_skippedpages)} will be substituted with the number of pages
previously sent, a useful value to include in a continuation cover page. Conditionals (Genshi's py:if) make it easy to provide different verbiage for continuation versus initial cover pages, distinguish between continuation cover pages where errors are provided (as in the case of an automatic resend done by HylaFAX) and those were it isn't (as when a partial job is sent using HylaFAX+'s new skippedpages functionality to start a job partway through).


The file "friendly.errorcodes" contains a translation table of simplified versions of HylaFAX+'s possible error codes; this lookup is exported by mkcover-svg to the environment. I'm not sure how this would need to change to work with the hylafax.org tree; likewise, the logic which adds a prefix onto environment variables read from the qfile is presently specific to hylafax+'s version of parseQfile, but there's a good chance you're going to want to edit that anyhow (if you want to use variables in your template which the bundled version doesn't export).

ContCoverCmd should be set to bin/mkcover-svg, and ContCoverPage should be set to the path to your SVG template.

Note that the sample coverpage is much simplified from what we use internally -- ours has domain-specific verbiage -- and I've cut out some pieces related to our local practice of encoding extra variables in the job tag, which most folks probably won't have need to do. Hopefully, everything works as presented here; however, the de-customized versions haven't been tested -- so feel free to ask for any pointers which may be needed. Please use Inkscape for viewing the provided template -- the SVG viewer built into Firefox doesn't like flowed text (which is a SVG 1.2 feature which Inkscape has made available even in SVG 1.0 mode -- and pretty much essential for anything like a comments field where information may need to be split across multiple lines of text).

All attached content was initially created on behalf of Catalis, Inc., and is released into the public domain. (I believe that I've sanitized any trademark references from the attachments, but to the extent that any remain, permission is *not* granted to use our or any other trademarks in connection with this code).

Have fun!
#!/usr/bin/env python

import optparse
import os
import sys

from genshi.template import MarkupTemplate

op = optparse.OptionParser(usage='%prog infile')
options, args = op.parse_args()

if len(args) != 1:
	op.error('exactly one argument must be provided')

tmpl = MarkupTemplate(open(args[0], 'r').read())
print tmpl.generate(**dict(os.environ))

#!/bin/bash

set -e

QFILE="$1"
TEMPLATE="$2"
RESULT="$3"

source etc/setup.cache
source bin/common-functions
source etc/friendly.errorcodes
parseQfile "QFILE_"
export "${!QFILE_@}"

if [ -n etc/debugging_enabled ] ; then
	DEBUG=1
else
	DEBUG=""
fi
export DEBUG

DEST_lastSendFailure_num=$(egrep -o '\{E[0-9]+\}' <<<"${DEST_lastSendFailure}" | tr -d '[{}]')
DEST_lastSendFailure_friendly="${!DEST_lastSendFailure_num}"
DEST_lastDialFailure_num=$(egrep -o '\{E[0-9]+\}' <<<"${DEST_lastDialFailure}" | tr -d '[{}]')
DEST_lastDialFailure_friendly="${!DEST_lastDialFailure_num}"
if [ -n "$DEST_dialFailures" -a "$DEST_dialFailures" -gt 0 ] ; then
	DEST_lastFailure="$DEST_lastDialFailure"
	DEST_lastFailure_num="$DEST_lastDialFailure_num"
	DEST_lastFailure_friendly="$DEST_lastDialFailure_friendly"
else
	DEST_lastFailure="$DEST_lastSendFailure"
	DEST_lastFailure_num="$DEST_lastSendFailure_num"
	DEST_lastFailure_friendly="$DEST_lastSendFailure_friendly"
fi
export "${!DEST_@}"
export PAGES_SENT="$(( ${QFILE_npages} + ${QFILE_skippedpages} ))"

TEMP_SVG="$(mktemp -t mkcover.svg.$$.XXXXXX)"
TEMP_PDF="$(mktemp -t mkcover.pdf.$$.XXXXXX)"
function cleanup() {
	rm -f "$TEMP_SVG" "$TEMP_PDF"
}
trap cleanup 0

bin/evaluate-template "$TEMPLATE" > "$TEMP_SVG"

[ -n "$DEBUG" ] && cat $TEMP_SVG

inkscape \
	--without-gui \
	--file="$TEMP_SVG" \
	--export-area-canvas \
	--export-pdf="$TEMP_PDF"

pdf2ps "$TEMP_PDF" "$RESULT"

image/svg

E000="Call successful"
E001="Busy signal"
E002="No fax communication"
E003="No answer"
E004="Unable to dial number"
E005="Problem dialing number"
E006="Unknown problem"
E007="Fax communication error"
E008="Fax communication error"
E009="Unable to initiate fax"
E010="Cannot redial so quickly"
E011="No fax communication"
E012="No fax communication"
E050="Fax communication error"
E051="Fax interruption"
E100="Fax communication error"
E101="Fax communication error"
E102="Fax communication error"
E103="Fax communication error"
E104="Fax communication error"
E105="Fax communication error"
E106="Fax communication error"
E107="Fax communication error"
E108="Fax communication error"
E109="Fax communication error"
E110="Fax communication error"
E111="Fax communication error"
E112="Fax communication error"
E113="Fax communication error"
E114="Fax communication error"
E115="Fax communication error"
E116="Fax communication error"
E117="Fax communication error"
E118="Fax communication error"
E119="Fax communication error"
E120="Fax communication error"
E121="Fax communication error"
E122="Fax communication error"
E123="Fax communication error"
E124="Fax communication error"
E125="Fax communication error"
E126="Fax communication error"
E127="Fax communication error"
E128="Fax communication error"
E129="Fax communication error"
E130="Fax communication error"
E131="Fax communication error"
E132="Fax communication error"
E133="Fax communication error"
E134="Fax communication error"
E135="Fax communication error"
E136="Fax communication error"
E137="Fax communication error"
E138="Fax communication error"
E139="Fax communication error"
E140="Fax communication error"
E141="Fax communication error"
E142="Fax communication error"
E143="Fax communication error"
E144="Fax communication error"
E145="Fax communication error"
E146="Fax communication error"
E147="Fax communication error"
E148="Fax communication error"
E149="Fax communication error"
E150="Fax communication error"
E151="Fax communication error"
E152="Fax communication error"
E153="Fax communication error"
E154="Fax communication error"
E155="Fax communication error"
E301="Fax interrupted"
E302="Problem with fax document"
E303="Fax processing error"
E304="Page limit exceeded"
E305="Fax processing error"
E306="Fax processing error"
E307="Fax processing error"
E308="Call rejected"
E309="Call ignored"
E310="Fax processing error"
E311="Fax processing error"
E312="Fax processing error"
E313="Fax processing error"
E314="Fax processing error"
E315="Fax processing error"
E316="Problem with fax document"
E317="Page limit exceeded"
E318="Fax processing error"
E319="Fax processing error"
E320="Fax processing error"
E321="Problem with fax document"
E322="Problem with fax document"
E323="Problem with fax document"
E324="Unsupported request"
E325="Fax took too long to deliver"
E326="Fax processing error"
E327="Problem with fax number"
E328="Unavailable device"
E329="Problem with fax document"
E330="Invalid fax document"
E331="Invalid fax request"
E332="Invalid fax request"
E333="Too many dials made"
E334="Too many communication attempts have failed"
E335="Too many pages in fax"
E336="Device does not support sending faxes"
E337="Waiting for other calls to finish"
E338="Fax delayed"
E339="Fax delayed"
E340="Fax processing error"
E341="Fax processing error"
E342="Fax delayed"
E343="Fax processing error"
E344="Fax interruption"
E345="Fax aborted"
E400="Unavailable feature requested"
E401="Unavailable feature requested"
E402="Fax processing error"
E403="Fax delivery error"
E404="Fax delivery error"
E405="Fax delivery error"
E406="Fax delivery error"
E407="Fax delivery error"
E408="Fax delivery error"
E409="Fax delivery error"
E410="Fax delivery error"
E411="Fax delivery error"
E412="Fax delivery error"
E413="Fax delivery error"
E414="Fax delivery error"
E415="Fax delivery error"
E416="Fax delivery error"
E417="Fax delivery error"
E418="Fax delivery error"
E419="Fax delivery error"



Project hosted by iFAX Solutions