Andrea Gabellini
Nico Garcia
John Gilman
+ Philip Gwyn
Craig Haskins
Kris Henderson
Wolfgang Henke
PATHGETTY PATH_GETTY
PATHVGETTY PATH_VGETTY
PATHEGETTY PATH_EGETTY
+PCL6CMD
PKG_ARCH
PKG_EMAIL
PKG_VENDOR
test "$MAN" || MAN=`findAppDef man $PATH man`
test "$MKDIR" || MKDIR=`findAppDef mkdir $PATH mkdir`
test "$MV" || MV=`findAppDef mv $PATH mv`
+test "$PCL6CMD" || PCL6CMD=`findAppDef pcl6 $PATH pcl6`
test "$PWDCMD" || PWDCMD=`findAppDef pwd $PATH pwd`
test "$RMCMD" || RMCMD=`findAppDef rm $PATH rm`
test "$SORT" || SORT=`findAppDef sort $PATH sort`
LN_S=@LN_S@ # ln option for creating a symbolic link
MKFIFO=@MKFIFO@ # FIFO creation program for use below
MV=@MV@ # move file for use below
+PCL6CMD=@PCL6CMD@ # pcl6 (GhostPCL) program
RMCMD=@RM@ # remove file for use below
SCRIPT_SH=@SCRIPT_SH@ # shell for use below
SED=@SED@ # sed for use below
PATHGETTY PATH_GETTY
PATHVGETTY PATH_VGETTY
PATHEGETTY PATH_EGETTY
+PCL6CMD
PSPACKAGE PS
QPENCODE
RM RMCMD
fi
fi
+test -x "$PCL6CMD" || {
+ PCL6CMD=`findAppDef pcl6 $PATH pcl6`
+ test -x "$PCL6CMD" && Note "Found PCL converter: $PCL6CMD"
+}
+
test -x "$UUENCODE" || {
UUENCODE=`findAppDef uuencode $PATH uuencode`
test -x "$UUENCODE" && Note "Found uuencode encoder: $UUENCODE"
{
fprintf(fd, "%s", filename);
}
-
-static bool
-isTIFF(const TIFFHeader& h)
-{
- if (h.tiff_magic != TIFF_BIGENDIAN && h.tiff_magic != TIFF_LITTLEENDIAN)
- return (false);
- union {
- int32 i;
- char c[4];
- } u;
- u.i = 1;
- uint16 version = h.tiff_version;
- // byte swap version stamp if opposite byte order
- if ((u.c[0] == 0) ^ (h.tiff_magic == TIFF_BIGENDIAN))
- TIFFSwabShort(&version);
- return (version == TIFF_VERSION);
-}
-
-bool
-HylaFAXServer::docType(const char* docname, FaxSendOp& op)
-{
- op = FaxRequest::send_unknown;
- int fd = Sys::open(docname, O_RDONLY);
- if (fd >= 0) {
- struct stat sb;
- if (FileCache::lookup(docname, sb) && S_ISREG(sb.st_mode)) {
- union {
- char buf[512];
- TIFFHeader h;
- } b;
- ssize_t cc = Sys::read(fd, (char*) &b, sizeof (b));
- if (cc > 2 && b.buf[0] == '%' && b.buf[1] == '!')
- op = FaxRequest::send_postscript;
- else if (cc > 2 && b.buf[0] == '%' && b.buf[1] == 'P') {
- logDebug("What we have here is a PDF file");
- op = FaxRequest::send_pdf;
- }
- else if (cc > (ssize_t)sizeof (b.h) && isTIFF(b.h))
- op = FaxRequest::send_tiff;
- else
- op = FaxRequest::send_data;
- }
- Sys::close(fd);
- }
- if (op == FaxRequest::send_unknown)
- logError("Don't know what file");
-
- return (op != FaxRequest::send_unknown);
-}
#endif
#endif /* CHAR_BIT */
-#define HAVE_PSLEVEL2 false
-#define HAVE_PCL5 false
static struct {
const char* name; // protocol token name
bool supported; // true if format is supported
const char* suffix; // file suffix
const char* help; // help string for HELP FORM command
+ FaxSendOp op; // associated FaxSendOp value
} formats[] = {
-{ "TIFF", true, "tif", "Tagged Image File Format, Class F only" },
-{ "PS", true, "ps", "Adobe PostScript Level I" },
-{ "PS2", HAVE_PSLEVEL2, "ps", "Adobe PostScript Level II" },
-{ "PCL", HAVE_PCL5, "pcl", "HP Printer Control Language (PCL), Version 5"},
-{ "PDF", true, "pdf", "Adobe Portable Document Format" },
+{ "TIFF", true, "tif", "Tagged Image File Format, Class F only", FaxRequest::send_tiff },
+{ "PS", true, "ps", "Adobe PostScript Level I", FaxRequest::send_postscript },
+{ "PCL", true, "pcl", "HP Printer Control Language (PCL)", FaxRequest::send_pcl},
+{ "PDF", true, "pdf", "Adobe Portable Document Format", FaxRequest::send_pdf}
};
+
static const char* typenames[] = { "ASCII", "EBCDIC", "Image", "Local" };
static const char* strunames[] = { "File", "Record", "Page", "TIFF" };
static const char* modenames[] = { "Stream", "Block", "Compressed", "ZIP" };
#define N(a) (sizeof (a) / sizeof (a[0]))
+
+static bool
+isTIFF(const TIFFHeader& h)
+{
+ if (h.tiff_magic != TIFF_BIGENDIAN && h.tiff_magic != TIFF_LITTLEENDIAN)
+ return (false);
+ union {
+ int32 i;
+ char c[4];
+ } u;
+ u.i = 1;
+ uint16 version = h.tiff_version;
+ // byte swap version stamp if opposite byte order
+ if ((u.c[0] == 0) ^ (h.tiff_magic == TIFF_BIGENDIAN))
+ TIFFSwabShort(&version);
+ return (version == TIFF_VERSION);
+}
+
+
/*
* Record a file transfer in the log file.
*/
}
reply(504, "Unknown format %s.", name);
}
+
+/*
+ * This is used to identify a submitted document type when the client
+ * specified the default (Postscript, legacy) or did not make a specification.
+ * If the file extension is not unknown, or or is Postscript, we'll check
+ * it, otherwise we'll trust it.
+ */
+bool
+HylaFAXServer::docType(const char* docname, FaxSendOp& op)
+{
+ op = FaxRequest::send_unknown;
+
+ fxStr file(docname);
+ u_int d = file.nextR(file.length(), '.');
+ if (strcmp(docname+d, "ps") != 0) {
+ /*
+ * Since it's not Postscript, let's look for it in ourlist of
+ * supported formats.
+ */
+ for (u_int i = 0, n = N(formats); i < n; i++) {
+ if (strcmp(docname+d, formats[i].suffix) == 0 && formats[i].supported) {
+ op = formats[i].op;
+ return (true);
+ }
+ }
+ }
+
+ /*
+ * The file extension is either Postscript (which is default on old
+ * clients, so no guarantee) or un-recognized, so let's take a peek
+ * and see if we can figure it out.
+ * XXX: Should we rename it if we find it successful?
+ */
+ int fd = Sys::open(docname, O_RDONLY);
+ if (fd >= 0) {
+ struct stat sb;
+ if (FileCache::lookup(docname, sb) && S_ISREG(sb.st_mode)) {
+ union {
+ char buf[512];
+ TIFFHeader h;
+ } b;
+ ssize_t cc = Sys::read(fd, (char*) &b, sizeof (b));
+ if (cc > 2 && b.buf[0] == '%' && b.buf[1] == '!')
+ op = FaxRequest::send_postscript;
+ else if (cc > 2 && b.buf[0] == '%' && b.buf[1] == 'P') {
+ logDebug("What we have here is a PDF file");
+ op = FaxRequest::send_pdf;
+ } else if (cc > 2 && b.buf[0] == 0x1b && (b.buf[1] == 'E' || b.buf[1] == '%' || b.buf[1] == '&' || b.buf[1] == '*')) {
+ logDebug("What we have here is a PCL file");
+ op = FaxRequest::send_pcl;
+ } else if (cc > (ssize_t)sizeof (b.h) && isTIFF(b.h))
+ op = FaxRequest::send_tiff;
+ else if (cc > 3 && b.buf[0] == '@' && b.buf[1] == 'P' && b.buf[2] == 'J' && b.buf[3] == 'L') {
+ logDebug("PJL is unsupported");
+ op = FaxRequest::send_unknown;
+ }
+ else
+ op = FaxRequest::send_data;
+ }
+ Sys::close(fd);
+ }
+ if (op == FaxRequest::send_unknown)
+ logError("Don't know what file");
+
+ return (op != FaxRequest::send_unknown);
+}
#undef N
void
return (false);
}
+
/*
* Add a cover document to the current job's
* set of documents that are to be sent.
fileSent = setFormat(FORM_TIFF)
&& setType(TYPE_I)
&& sendData(fd, &FaxClient::storeTemp, info.doc, emsg);
+ } else if (info.rule->getResult() == TypeRule::PCL) {
+ fileSent = setFormat(FORM_PCL)
+ && setType(TYPE_I)
+ && sendData(fd, &FaxClient::storeTemp, info.doc, emsg);
} else if (info.rule->getResult() == TypeRule::PDF) {
fileSent = setFormat(FORM_PDF)
&& setType(TYPE_I)
return (false);
}
info.temp = tmpFile;
- } else // already postscript, pdf, or tiff
+ } else // already postscript, pdf, pcl, or tiff
info.temp = info.name;
switch (info.rule->getResult()) {
case TypeRule::TIFF:
countTIFFPages(info.temp);
break;
+ case TypeRule::PCL:
+ // maybe use pclcount/pcl6count from http://www.fea.unicamp.br/pclcount/
+ break;
case TypeRule::POSTSCRIPT:
case TypeRule::PDF:
estimatePostScriptPages(info.temp);
{ "ascii", "asciiesc", "string", "istring" "address", "byte", "short", "long" };
static const char* opNames[] =
{ "<any>", "=", "!=", "<", "<=", ">", ">=", "&", "^", "!" };
-static const char* resultNames[] = { "tiff", "postscript", "pdf", "error" };
+static const char* resultNames[] = { "tiff", "postscript", "pdf", "pcl", "error" };
fxStr
quoted(const fxStr& s)
rule.result = TypeRule::POSTSCRIPT;
else if (strncasecmp(rp, "pdf", cp-rp) == 0)
rule.result = TypeRule::PDF;
+ else if (strncasecmp(rp, "pcl", cp-rp) == 0)
+ rule.result = TypeRule::PCL;
else if (strncasecmp(rp, "error", cp-rp) == 0)
rule.result = TypeRule::ERROR;
else {
* and embedded spaces, but not embedded tabs, are allowed.
* These data are taken literally; no C-style character escapes
* are meaningful.
- * result: one of "PS", "TIFF", "PDF", or "error" (case insensitive). The
- * first two results specifiy whether the rule generates a PostScript
+ * result: one of "PS", "TIFF", "PDF", "PCL", or "error" (case insensitive).
+ * The first two results specifiy whether the rule generates a PostScript
* file or a bilevel TIFF image. The "error" result indicates a
* file is unsuitable for transmission and if supplied as an
* argument to sendfax, the command should be aborted.
TIFF, // bilevel Group 3-encoded TIFF
POSTSCRIPT, // PostScript
PDF, // Portable Document Format
+ PCL, // Printer Control Language
ERROR // recognized erronious format
};
private:
# and embedded spaces, but not embedded tabs, are allowed.
# These data are taken literally; no C-style character escapes
# are meaningful.
-# result: one of "PS", "TIFF", "PDF", or "error" (case insensitive). The
-# first two results specifiy whether the rule generates a PostScript
+# result: one of "PS", "TIFF", "PDF", "PCL", or "error" (case insensitive).
+# The first two results specifiy whether the rule generates a PostScript
# file or a bilevel TIFF image. The "error" result indicates a
# file is unsuitable for transmission and if supplied as an
# argument to sendfax, the command should be aborted.
>3 string 87a tiff gif2tiff -%f -v %V %i %o
>3 string 89a error GIF (version 89a) support not configured
0 long 0x59a66a95 tiff ras2tiff -%f -v %V %i %o
+0 short 0x1b45 pcl
+0 short 0x1b25 pcl
+0 short 0x1b26 pcl
+0 short 0x1b2a pcl
+#
+# To do client-side PCL conversion to PostScript comment-out the above
+# and uncomment this:
+#0 short 0x1b25 ps pcl6 -dNOPAUSE -sDEVICE=pswrite -sOutputFile=%o %i
#
# HylaFAX now has server-side PDF conversion, so no need for pdf2ps.
# If you have trouble or if you prefer to use pdf2ps, comment this
The command to invoke to convert a HP-PCL document submitted
for transmission to
.SM TIFF/F,
-suitable for transmission (for future use).
+suitable for transmission.
.TP
.B PercentGoodLines
The minimum percentage of good rows of image data required
directory).
\*(Fx accepts \*(Ps, PDF, \*(Pc, and
.SM TIFF
-documents for transmission (though support for
-\*(Pc documents is not currently implemented).
+documents for transmission (support for \*(Pc documents
+requires an external application).
Documents are automatically converted to
.SM TIFF/F
documents prior to transmission according to the capabilities
# Convert PCL to facsimile.
#
# pcl2fax [-o output] [-l pagelength] [-w pagewidth]
-# [-r resolution] [-m maxpages] [-*] file ...
+# [-r resolution] [-m maxpages] [-*] files ...
#
# NB: this shell script is assumed to be run from the
# top of the spooling hierarchy -- s.t. the etc directory
}
. etc/setup.cache
-echo "PCL documents are not (currently) supported."
-exit 254 # causes document to be rejected
+if [ ! -x "$PCL6CMD" ]; then
+ echo "PCL documents are not (currently) supported."
+ exit 254 # causes document to be rejected
+fi
+
+out=pcl.fax # default output filename
+pagewidth=1728 # standard fax width (pixels)
+pagelength=297 # default to A4 (mm)
+vres=98 # default to low res
+device=tiffg3 # default to 1D
+unlimitedlength=no # default to fixed length-pages
+jobid=
+out=pcl.fax # default output filename
+files=
+opt=
+while test $# != 0
+do case "$1" in
+ -o) shift; out=$1 ;;
+ -w) shift; pagewidth="$1" ;;
+ -l) shift; pagelength="$1" ;;
+ -r) shift; vres="$1" ;;
+ -m) shift;; # NB: not implemented
+ -U) unlimitedlength=yes ;;
+ -1) device=tiffg3 ;;
+ -2) ($PCL -h | grep tiffg32d >/dev/null 2>&1) \
+ && { device=tiffg32d; } \
+ || { device=tiffg3; }
+ ;;
+ -3) ($PCL -h | grep tiffg4 >/dev/null 2>&1) \
+ && { device=tiffg4; } \
+ || { device=tiffg3; }
+ ;;
+ -*) ;;
+ *) files="$files $1" ;;
+ esac
+ shift
+done
+
+test -z "$files" && {
+ echo "$0: No input file specified."
+ exit 255
+}
+
+pagelength=${pagelength%%.*}
+test "$pagewidth" = "1734" && pagewidth=1728
+
+case "${pagewidth}x${pagelength}" in
+1728x280|1728x279|2592x280|2592x279|3456x280|3456x279) # 279.4mm is actually correct...
+ paper=letter;;
+1728x364|2592x364|3456x364)
+ paper=legal;;
+*x296|*x297) # more roundoff problems...
+ paper=a4;;
+*x364)
+ paper=b4;;
+2432x*|3648x*|4864x*)
+ paper=a3;;
+*)
+ echo "$0: Unsupported page size: $pagewidth x $pagelength";
+ exit 254;; # causes document to be rejected
+esac
+#
+# The image must end up with a pixel width according to T.32 Table 21.
+# Ghostscript contains code to fixate a4 and letter to 1728 pixels
+# when using 196-204 dpi and tiffg3/4, it supposedly does the same for
+# B4 but not for A3, thus the floats are needed (for A3's benefit).
+#
+# See ghostscript/doc/Devices.htm under -dAdjustWidth=1 (default).
+# Use -dAdjustWidth=0 to disable. With the right patch,
+# http://bugs.ghostscript.com/show_bug.cgi?id=688064
+# AdjustWidth can be made to specify the pagewidth directly and
+# replace -dFIXEDMEDIA to permit TIFFs to be produced with
+# varied lengths.
+#
+case "$paper" in
+ a4)
+ case "$pagewidth" in
+ 2592) hres=313.65;; # VR_300X300
+ 3456) hres=418.20;; # VR_R16
+ *) hres=209.10;; # everything else, 1728 pixels
+ esac;;
+ b4)
+ case "$pagewidth" in
+ 3072) hres=311.97;; # VR_300X300
+ 4096) hres=415.95;; # VR_R16
+ *) hres=207.98;; # everything else, 2048 pixels
+ esac;;
+ a3)
+ case "$pagewidth" in
+ 3648) hres=311.94;; # VR_300X300
+ 4864) hres=415.93;; # VR_R16
+ *) hres=207.96;; # everything else, 2432 pixels
+ esac;;
+ *) # letter, legal
+ case "$pagewidth" in
+ 2592) hres=304.94;; # VR_300X300
+ 3456) hres=406.59;; # VR_R16
+ *) hres=203.29;; # everything else, 1728 pixels
+ esac;;
+esac
+
+#
+# The sed work fixes bug in Windows-generated
+# PostScript that causes certain international
+# character marks to be placed incorrectly.
+#
+# | $SED -e 's/yAscent Ascent def/yAscent 0 def/g' \
+#
+# NB: unfortunately it appears to break valid PostScript;
+# so it's been disabled.
+
+#
+# Suggestion from "Alan Sparks" <asparks@nss.harris.com>,
+# Add the -DFIXEDMEDIA argument to the last command in pcl2fax.
+# This prevents page sizing within the documents from altering
+# the command-line page size specification. This prevents
+# TIFFs to be made with pages of varied lengths, however.
+# See the comments on AdjustWidth above.
+#
+FIXEDWIDTH="-dFIXEDMEDIA"
+
+#
+# Apply customizations such as watermarking.
+#
+if [ -f etc/FaxModify ]; then
+ . etc/FaxModify
+fi
+
+# For debuging
+false && echo $PCL6 \
+ -sDEVICE=$device \
+ -dNOPAUSE \
+ -dSAFER=true \
+ -sPAPERSIZE=$paper \
+ $FIXEDWIDTH \
+ -r$hres\x$vres \
+ "-sOutputFile=$out" \
+ "$files"
+
+if [ ! "$PCLFONTSOURCE" -a -n "$FONTPATH" ] ; then
+ PCLFONTSOURCE=$FONTPATH
+fi
+if [ -n "$PCLFONTSOURCE" ] ; then
+ export PCLFONTSOURCE
+fi
+
+$CAT $files | $PCL6 \
+ -sDEVICE=$device \
+ -dNOPAUSE \
+ -dSAFER=true \
+ -sPAPERSIZE=$paper \
+ $FIXEDWIDTH \
+ -r$hres\x$vres \
+ "-sOutputFile=$out" \
+ -
+
+exit 0