/*****************************************************************************\
hpcupsfax.cpp : HP CUPS fax filter
Copyright (c) 2001 - 2010, HP Co.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the Hewlett-Packard nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PATENT INFRINGEMENT; PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
\*****************************************************************************/
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <syslog.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdint.h>
#include <time.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <math.h>
#include <cups/cups.h>
#include <cups/ppd.h>
#include <cups/raster.h>
#include <string>
#ifdef FALSE
#undef FALSE
#endif
#ifdef TRUE
#undef TRUE
#endif
#include "hpip.h"
#include "hpcupsfax.h"
#include "bug.h"
#include "utils.h"
using namespace std;
int fax_encoding = RASTER_MMR;
char device_name[16];
BYTE szFileHeader[68];
BYTE szPageHeader[64];
uint32_t (*convert_endian_l)(uint32_t);
uint16_t (*convert_endian_s)(uint16_t);
static int iLogLevel = 1;
char hpFileName[MAX_FILE_PATH_LEN] ;
#define TIFF_HDR_SIZE 8
#define LITTLE_ENDIAN_MODE I
#define BIG_ENDIAN_MODE M
#define DBG(args...) syslog(LOG_INFO, __FILE__ " " STRINGIZE(__LINE__) ": " args)
// GrayLevel = (5/16)R + (9/16)G + (2/16)B
#define RGB2BW(r, g, b) (BYTE) (((r << 2) + r + (g << 3) + g + (b << 1)) >> 4)
void RGB2Gray (BYTE *pRGBData, int iNumPixels, BYTE *pGData)
{
int i;
BYTE *pIn = pRGBData;
BYTE *pOut = pGData;
for (i = 0; i < iNumPixels; i++, pIn += 3)
{
*pOut++ = RGB2BW ((unsigned short) *pIn, (unsigned short) pIn[1], (unsigned short) pIn[2]);
}
}
static void GetLogLevel ()
{
FILE *fp;
char str[258];
char *p;
fp = fopen ("/etc/cups/cupsd.conf", "r");
if (fp == NULL)
return;
while (!feof (fp))
{
if (!fgets (str, 256, fp))
{
break;
}
if ((p = strstr (str, "hpLogLevel")))
{
p += strlen ("hpLogLevel") + 1;
iLogLevel = atoi (p);
break;
}
}
fclose (fp);
}
void PrintCupsHeader (cups_page_header2_t m_cupsHeader)
{
if (iLogLevel == 0)
{
return;
}
BUG ("DEBUG: HPFAX - startPage...\n");
BUG ("DEBUG: HPFAX - MediaClass = \"%s\"\n", m_cupsHeader.MediaClass);
BUG ("DEBUG: HPFAX - MediaColor = \"%s\"\n", m_cupsHeader.MediaColor);
BUG ("DEBUG: HPFAX - MediaType = \"%s\"\n", m_cupsHeader.MediaType);
BUG ("DEBUG: HPFAX - OutputType = \"%s\"\n", m_cupsHeader.OutputType);
BUG ("DEBUG: HPFAX - AdvanceDistance = %d\n", m_cupsHeader.AdvanceDistance);
BUG ("DEBUG: HPFAX - AdvanceMedia = %d\n", m_cupsHeader.AdvanceMedia);
BUG ("DEBUG: HPFAX - Collate = %d\n", m_cupsHeader.Collate);
BUG ("DEBUG: HPFAX - CutMedia = %d\n", m_cupsHeader.CutMedia);
BUG ("DEBUG: HPFAX - Duplex = %d\n", m_cupsHeader.Duplex);
BUG ("DEBUG: HPFAX - HWResolution = [ %d %d ]\n", m_cupsHeader.HWResolution[0], m_cupsHeader.HWResolution[1]);
BUG ("DEBUG: HPFAX - ImagingBoundingBox = [ %d %d %d %d ]\n",
m_cupsHeader.ImagingBoundingBox[0], m_cupsHeader.ImagingBoundingBox[1],
m_cupsHeader.ImagingBoundingBox[2], m_cupsHeader.ImagingBoundingBox[3]);
BUG ("DEBUG: HPFAX - InsertSheet = %d\n", m_cupsHeader.InsertSheet);
BUG ("DEBUG: HPFAX - Jog = %d\n", m_cupsHeader.Jog);
BUG ("DEBUG: HPFAX - LeadingEdge = %d\n", m_cupsHeader.LeadingEdge);
BUG ("DEBUG: HPFAX - Margins = [ %d %d ]\n", m_cupsHeader.Margins[0], m_cupsHeader.Margins[1]);
BUG ("DEBUG: HPFAX - ManualFeed = %d\n", m_cupsHeader.ManualFeed);
BUG ("DEBUG: HPFAX - MediaPosition = %d\n", m_cupsHeader.MediaPosition);
BUG ("DEBUG: HPFAX - MediaWeight = %d\n", m_cupsHeader.MediaWeight);
BUG ("DEBUG: HPFAX - MirrorPrint = %d\n", m_cupsHeader.MirrorPrint);
BUG ("DEBUG: HPFAX - NegativePrint = %d\n", m_cupsHeader.NegativePrint);
BUG ("DEBUG: HPFAX - NumCopies = %d\n", m_cupsHeader.NumCopies);
BUG ("DEBUG: HPFAX - Orientation = %d\n", m_cupsHeader.Orientation);
BUG ("DEBUG: HPFAX - OutputFaceUp = %d\n", m_cupsHeader.OutputFaceUp);
BUG ("DEBUG: HPFAX - PageSize = [ %d %d ]\n", m_cupsHeader.PageSize[0], m_cupsHeader.PageSize[1]);
BUG ("DEBUG: HPFAX - Separations = %d\n", m_cupsHeader.Separations);
BUG ("DEBUG: HPFAX - TraySwitch = %d\n", m_cupsHeader.TraySwitch);
BUG ("DEBUG: HPFAX - Tumble = %d\n", m_cupsHeader.Tumble);
BUG ("DEBUG: HPFAX - cupsWidth = %d\n", m_cupsHeader.cupsWidth);
BUG ("DEBUG: HPFAX - cupsHeight = %d\n", m_cupsHeader.cupsHeight);
BUG ("DEBUG: HPFAX - cupsMediaType = %d\n", m_cupsHeader.cupsMediaType);
BUG ("DEBUG: HPFAX - cupsRowStep = %d\n", m_cupsHeader.cupsRowStep);
BUG ("DEBUG: HPFAX - cupsBitsPerColor = %d\n", m_cupsHeader.cupsBitsPerColor);
BUG ("DEBUG: HPFAX - cupsBitsPerPixel = %d\n", m_cupsHeader.cupsBitsPerPixel);
BUG ("DEBUG: HPFAX - cupsBytesPerLine = %d\n", m_cupsHeader.cupsBytesPerLine);
BUG ("DEBUG: HPFAX - cupsColorOrder = %d\n", m_cupsHeader.cupsColorOrder);
BUG ("DEBUG: HPFAX - cupsColorSpace = %d\n", m_cupsHeader.cupsColorSpace);
BUG ("DEBUG: HPFAX - cupsCompression = %d\n", m_cupsHeader.cupsCompression);
BUG ("DEBUG: HPFAX - cupsPageSizeName = %s\n", m_cupsHeader.cupsPageSizeName);
}
int GetPageSizeFromString(char *string)
{
int iPageSize = atoi(string);
if(iPageSize == 0)
{
if(strcmp(string,"Letter") ==0){
iPageSize = 1;
}
else if(strcmp(string,"A4") ==0){
iPageSize = 2;
}
else if(strcmp(string,"Legal") ==0){
iPageSize = 3;
}
else{
DBG("hpcupsfax: GetPageSizeFromString:Default Page Size is taken,ensure it is ok.\n");
iPageSize = 1;
}
}
DBG("hpcupsfax: GetPageSizeFromString: PageSize = %d\n",iPageSize);
return iPageSize;
}
int ProcessRasterData (cups_raster_t *cups_raster, int fdFax)
{
int status = 0;
unsigned int i;
int widthMMR;
int iInputBufSize;
BYTE *pThisScanLine;
LPBYTE pbOutputBuf = NULL;
LPBYTE pInputBuf = NULL;
IP_XFORM_SPEC xForm[3];
IP_IMAGE_TRAITS traits;
IP_HANDLE hJob;
BYTE *p;
cups_page_header2_t cups_header;
int iPageNum = 0;
int color_mode;
char *pDev;
unsigned int uiPageNum = 0;
pDev = getenv ("DEVICE_URI");
while (cupsRasterReadHeader2 (cups_raster, &cups_header))
{
iPageNum++;
if (iPageNum == 1)
{
PrintCupsHeader (cups_header);
color_mode = (cups_header.cupsRowStep == 0) ? HPLIPFAX_MONO : HPLIPFAX_COLOR;
if (color_mode == HPLIPFAX_COLOR)
{
fax_encoding = RASTER_JPEG;
}
memset (szFileHeader, 0, sizeof (szFileHeader));
memcpy (szFileHeader, "hplip_g3", 8);
p = szFileHeader + 8;
*p++ = 1; // Version Number
HPLIPPUTINT32 (p, 0); p += 4; // Total number of pages in this job
HPLIPPUTINT16 (p, cups_header.HWResolution[0]); p += 2;
HPLIPPUTINT16 (p, cups_header.HWResolution[1]); p += 2;
BUG("ATOI Value = %d",atoi (cups_header.cupsPageSizeName));
*p++ = GetPageSizeFromString(cups_header.cupsPageSizeName); // Output paper size
*p++ = atoi (cups_header.OutputType); // Output quality
*p++ = fax_encoding; // MH, MMR or JPEG
p += 4; // Reserved 1
p += 4; // Reserved 2
write (fdFax, szFileHeader, (p - szFileHeader));
}
widthMMR = (((cups_header.cupsWidth + 7) >> 3)) << 3;
/*
* Devices in the HPFax2 category require fixed width of 2528 pixels.
* Example: LaserJet 2727 MFP
*/
if (strcmp (device_name, "HPFax4") ==0)
{
widthMMR = 1728;
}
else if (!strcmp (device_name, "HPFax2"))
{
widthMMR = 2528;
}
iInputBufSize = widthMMR * cups_header.cupsHeight;
pInputBuf = (LPBYTE) malloc (iInputBufSize);
if (pInputBuf == NULL)
{
BUG ("Unable to allocate pInputBuf, size = %d\n", iInputBufSize);
goto BUGOUT;
}
memset (pInputBuf, 0xFF, iInputBufSize);
pThisScanLine = new BYTE[cups_header.cupsBytesPerLine];
if (pThisScanLine == NULL)
{
BUG ("Unable to allocate pThisScanLine, size = %d\n", cups_header.cupsBytesPerLine);
goto BUGOUT;
}
for (i = 0; i < cups_header.cupsHeight; i++)
{
cupsRasterReadPixels (cups_raster, pThisScanLine, cups_header.cupsBytesPerLine);
RGB2Gray (pThisScanLine, cups_header.cupsWidth, pInputBuf + i * widthMMR);
}
WORD wResult;
DWORD dwInputAvail;
DWORD dwInputUsed;
DWORD dwInputNextPos;
DWORD dwOutputAvail;
DWORD dwOutputUsed;
DWORD dwOutputThisPos;
pbOutputBuf = (LPBYTE) malloc (iInputBufSize);
if (pbOutputBuf == NULL)
{
BUG ("unable to allocate pbOutputBuf, buffer size = %d\n", iInputBufSize);
goto BUGOUT;
}
memset (pbOutputBuf, 0xFF, iInputBufSize);
memset (xForm, 0, sizeof (xForm));
if (color_mode == HPLIPFAX_MONO)
{
i = 0;
xForm[i].eXform = X_GRAY_2_BI;
// 0 - Error diffusion
// >0 - Threshold value
xForm[i].aXformInfo[IP_GRAY_2_BI_THRESHOLD].dword = 127;
i++;
xForm[i].eXform = X_FAX_ENCODE;
if (fax_encoding== RASTER_MMR)
{
xForm[i].aXformInfo[IP_FAX_FORMAT].dword = IP_FAX_MMR;
}
else
{
xForm[i].aXformInfo[IP_FAX_FORMAT].dword = IP_FAX_MH;
}
/* 0 = EOLs are in data as usual; */
/* 1 = no EOLs in data. */
xForm[i].aXformInfo[IP_FAX_NO_EOLS].dword = 0;
xForm[i].pXform = NULL;
xForm[i].pfReadPeek = NULL;
xForm[i].pfWritePeek = NULL;
i++;
wResult = ipOpen (i, xForm, 0, &hJob);
traits.iComponentsPerPixel = 1;
traits.iBitsPerPixel = 8;
}
else
{
xForm[0].eXform = X_CNV_COLOR_SPACE;
xForm[0].aXformInfo[IP_CNV_COLOR_SPACE_WHICH_CNV].dword = IP_CNV_SRGB_TO_YCC;
xForm[1].eXform = X_CNV_COLOR_SPACE;
xForm[1].aXformInfo[IP_CNV_COLOR_SPACE_WHICH_CNV].dword = IP_CNV_YCC_TO_CIELAB;
xForm[0].eXform = X_JPG_ENCODE;
xForm[0].aXformInfo[IP_JPG_ENCODE_FOR_COLOR_FAX].dword = 1;
wResult = ipOpen (1, xForm, 0, &hJob);
traits.iComponentsPerPixel = 3;
traits.iBitsPerPixel = 8;
}
if (wResult != IP_DONE)
{
BUG ("ipOpen failed: wResult = %x\n", wResult);
goto BUGOUT;
}
traits.iPixelsPerRow = widthMMR;
traits.lHorizDPI = cups_header.HWResolution[0];
traits.lVertDPI = cups_header.HWResolution[1];
traits.lNumRows = cups_header.cupsHeight;
traits.iNumPages = 1;
traits.iPageNum = 1;
wResult = ipSetDefaultInputTraits (hJob, &traits);
if (wResult != IP_DONE)
{
BUG ("ipSetDefaultInputTraits failed: wResult = %x\n", wResult);
wResult = ipClose (hJob);
goto BUGOUT;
}
dwInputAvail = iInputBufSize;
dwOutputAvail = dwInputAvail;
wResult = ipConvert (hJob, dwInputAvail, pInputBuf, &dwInputUsed,
&dwInputNextPos, dwOutputAvail, pbOutputBuf,
&dwOutputUsed, &dwOutputThisPos);
if (wResult == IP_FATAL_ERROR)
{
BUG ("ipConvert failed, wResult = %d\n", wResult);
goto BUGOUT;
}
if (iLogLevel > 0)
{
BUG ("dwInputAvail = %d dwInputUsed = %d dwOutputUsed = %d\n",
dwInputAvail, dwInputUsed, dwOutputUsed);
}
wResult = ipClose (hJob);
hJob = 0;
uiPageNum++;
p = szPageHeader;
HPLIPPUTINT32 (p, uiPageNum); p += 4; // Current page number
HPLIPPUTINT32 (p, widthMMR); p += 4; // Num of pixels per row
HPLIPPUTINT32 (p, cups_header.cupsHeight); p += 4; // Num of rows in this page
HPLIPPUTINT32 (p, dwOutputUsed); p += 4; // Size in bytes of encoded data
HPLIPPUTINT32 (p, 0); p += 4; // Thumbnail data size
HPLIPPUTINT32 (p, 0); p += 4; // Reserved for future use
write (fdFax, szPageHeader, (p - szPageHeader));
write (fdFax, pbOutputBuf, dwOutputUsed);
/*
* Write the thumbnail data here
*/
// Send this to fax handler
free (pbOutputBuf);
free (pInputBuf);
free (pThisScanLine);
pbOutputBuf = NULL;
pInputBuf = NULL;
pThisScanLine = NULL;
} /* end while (1) */
lseek (fdFax, 9, SEEK_SET);
HPLIPPUTINT32 ((szFileHeader + 9), uiPageNum);
write (fdFax, szFileHeader + 9, 4);
BUGOUT:
if (pbOutputBuf)
{
free (pbOutputBuf);
}
if (pInputBuf)
{
free (pInputBuf);
}
return status;
}
/*
* Return Zero if all the below are successful
* Reading from stdin into a temp file
* Getting the final file with HPLIP file and page headers
*/
int ProcessTiffData(int fromFD, int toFD, char* user_name)
{
BYTE *p;
int fdTiff;
BYTE pTmp[4096];
struct timeval tv;
fd_set fds;
int page_length;
unsigned int page_counter;
unsigned int current_ifd_start;
unsigned int *ifd_offset;
unsigned int next_ifd_offset;
unsigned short ifd_count;
bool big_endian = false;
int i, ret, len;
BYTE szTiffHeader[TIFF_HDR_SIZE];
int bytes_written = 0;
int ret_status = 0;
int bytes_read = 0;
char hpTiffFileName[MAX_FILE_PATH_LEN];
long input_file_size = 0;
FILE* pFilePtrFax;
snprintf(hpTiffFileName,sizeof(hpTiffFileName), "%s/hp_%s_fax_tiffXXXXXX",CUPS_TMP_DIR,user_name);
// fdTiff = mkstemp (hpTiffFileName);
fdTiff = createTempFile(hpTiffFileName, &pFilePtrFax);
if (fdTiff < 0)
{
BUG("ERROR: Unable to open Fax output file - %s for writing\n", hpTiffFileName);
return 1;
}
memset (szFileHeader, 0, sizeof (szFileHeader));
memcpy (szFileHeader, "hplip_g3", 8);
p = szFileHeader + 8;
*p++ = 1; // Version Number
HPLIPPUTINT32 (p, 0); p += 4; // Total number of pages in this job
HPLIPPUTINT16 (p, 0); p += 2; //HWResolution[0]
HPLIPPUTINT16 (p, 0); p += 2; //HWResolution[0]
*p++ = atoi ("0"); // Output paper size (cupsPageSizeName)
*p++ = atoi ("0"); // Output quality (cups OutputType)
*p++ = fax_encoding; // MH, MMR or JPEG, TIFF
p += 4; // Reserved 1
p += 4; // Reserved 2
write (toFD, szFileHeader, (p - szFileHeader));
FD_ZERO(&fds);
FD_SET(fromFD, &fds);
tv.tv_sec = 0;
tv.tv_usec = 100 * 1000; //100 ms
i = 0;
len = read (fromFD, pTmp, 4096);
if (len > 0) {
DBG("hpcupsfax: read %d bytes from stdin", len);
write (fdTiff, pTmp, len);
bytes_written += len;
} else {
DBG("hpcupsfax: No data was available...");
}
while (i++ < 10)
{
memset (pTmp, 0, 4096);
ret = select(fromFD+1, &fds, NULL, NULL, &tv);
if (ret < 0) {
DBG("hpcupsfax: Timed out, Continue...");
continue;
}
if (FD_ISSET(fromFD, &fds)) {
DBG("hpcupsfax: Data is available");
while(1) {
memset (pTmp, 0, 4096);
len = read (fromFD, pTmp, 4096);
DBG("hpcupsfax: read %d bytes from stdin", len);
if (len <= 0) {
DBG("hpcupsfax: No data was available, Continue...");
break; //break from inner while()
}
write (fdTiff, pTmp, len);
bytes_written += len;
}
}
}
DBG("hpcupsfax: total bytes written to fdTiff is %d ", bytes_written);
input_file_size = bytes_written;
ret = lseek (fdTiff, 0, SEEK_SET);
memset (szTiffHeader, 0, sizeof (TIFF_HDR_SIZE));
ret = read (fdTiff, szTiffHeader, 8);
DBG("hpcupsfax: read %d bytes from fdTiff", ret);
ifd_offset = (unsigned int *) &(szTiffHeader[4]);
if (szTiffHeader[0] == 'M') {
DBG("hpcupsfax: it is big endian");
big_endian = true;
*ifd_offset = ntohl(*ifd_offset);
}
DBG("hpcupsfax: ifd_offset is %d", *ifd_offset);
current_ifd_start = 0;
page_counter = 0;
bytes_written = 0;
//WHILE
while(1) {
// Note down the number of tags
ret = lseek (fdTiff, *ifd_offset, SEEK_SET);
ret = read (fdTiff, &ifd_count, 2);
if (big_endian) {
ifd_count = ntohs(ifd_count);
}
DBG("hpcupsfax: read %d bytes from fdTiff; ifd count is %d", ret, ifd_count);
// Read the end of IFD to check if there is another IFD following (for e.g., next page or image)
ret = lseek (fdTiff, (*ifd_offset+2+((ifd_count)*12)), SEEK_SET);
ret = read (fdTiff, &next_ifd_offset, 4);
if (big_endian) {
next_ifd_offset = ntohs(next_ifd_offset);
}
DBG("hpcupsfax: read %d bytes from fdTiff at %d; next ifd offset is %d",
ret, (*ifd_offset+2+((ifd_count)*12)), next_ifd_offset);
// Increment the page counter
page_counter = page_counter + 1;
DBG("hpcupsfax: Current page_counter is %d", page_counter);
// Write Tiff data for the current page (IFD)
page_length = next_ifd_offset-current_ifd_start;
DBG("hpcupsfax: page_length is %d ", page_length);
if (page_length <= 0) {
len = lseek (fdTiff, 0, SEEK_END);
page_length = len - current_ifd_start;
}
DBG("hpcupsfax: current_ifd_start=%d next_ifd_offset=%d total bytes are %d", current_ifd_start, next_ifd_offset, page_length);
// Write HPLIP page header
p = szPageHeader;
HPLIPPUTINT32 (p, page_counter); p += 4; // Current page number
HPLIPPUTINT32 (p, 0); p += 4; // Num of pixels per row - It is ImageWidth for Tiff
HPLIPPUTINT32 (p, 0); p += 4; // Num of rows in this page - It is ImageLength for Tiff
HPLIPPUTINT32 (p, page_length); p += 4; // Size in bytes of encoded data
HPLIPPUTINT32 (p, 0); p += 4; // Thumbnail data size
HPLIPPUTINT32 (p, 0); p += 4; // Reserved for future use
ret = write (toFD, szPageHeader, (p - szPageHeader));
ret = lseek (fdTiff, current_ifd_start, SEEK_SET);
while (page_length > 0) {
if (page_length < 4096) {
len = page_length;
} else {
len = 4096;
}
bytes_read = read (fdTiff, pTmp, len);
ret = write (toFD, pTmp, bytes_read);
page_length = page_length - ret;
bytes_written += ret;
}
// If there is no next IFD, break from the loop. Else, continue...
if (bytes_written > input_file_size) {
BUG("Error!! Bytes written to toFD is becoming more than input file size.");
ret_status = -1;
break; // while(1) for page counting
}
if (next_ifd_offset == 0) {
break; // while(1) for page counting
}
current_ifd_start = *ifd_offset = next_ifd_offset;
} // while(1) for page counting
lseek (toFD, 9, SEEK_SET);
HPLIPPUTINT32 ((szFileHeader + 9), page_counter);
write (toFD, szFileHeader + 9, 4);
if (!(iLogLevel & SAVE_PCL_FILE))
{
unlink(hpTiffFileName);
}
return ret_status;
}
int send_data_to_stdout(int fromFD)
{
int iSize, i;
int len;
BYTE *pTmp = NULL;
iSize = lseek (fromFD, 0, SEEK_END);
lseek (fromFD, 0, SEEK_SET);
DBG("hpcupsfax: lseek(fromFD) returned %d", iSize);
if (iSize > 0)
{
pTmp = (BYTE *) malloc (iSize);
}
if (pTmp == NULL)
{
iSize = 1024;
pTmp = (BYTE *) malloc (iSize);
if (pTmp == NULL)
{
return 1;
}
}
while ((len = read (fromFD, pTmp, iSize)) > 0)
{
write (STDOUT_FILENO, pTmp, len);
}
free (pTmp);
return 0;
}
int main (int argc, char **argv)
{
int status = 0;
int fd = 0;
int fdFax = -1;
int i = 0;
FILE *pFilePtrFax;
cups_raster_t *cups_raster;
ppd_file_t *ppd;
ppd_attr_t *attr;
ppd_attr_t *compression_attr;
/*********** PROLOGUE ***********/
GetLogLevel();
openlog("hpcupsfax", LOG_PID, LOG_DAEMON);
if (argc < 6 || argc > 7)
{
BUG ("ERROR: %s job-id user title copies options [file]\n", *argv);
return 1;
}
if (argc == 7)
{
if ((fd = open (argv[6], O_RDONLY)) == -1)
{
BUG ("ERROR: Unable to open raster file %s\n", argv[6]);
return 1;
}
}
while (argv[i] != NULL) {
DBG("hpcupsfax: argv[%d] = %s\n", i, argv[i]);
i++;
}
snprintf(hpFileName,sizeof(hpFileName),"%s/hp_%s_fax_Log_XXXXXX",CUPS_TMP_DIR, argv[2]);
// fdFax = mkstemp (hpFileName);
fdFax = createTempFile(hpFileName, &pFilePtrFax);
if (fdFax < 0)
{
BUG ("ERROR: Unable to open Fax output file - %s for writing\n", hpFileName);
return 1;
}
else
chmod(hpFileName, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP );
/*********** MAIN ***********/
ppd = ppdOpenFile (getenv ("PPD"));
if (ppd == NULL)
{
BUG ("ERROR: Unable to open ppd file %s\n", getenv ("PPD"));
return 1;
}
if ((attr = ppdFindAttr (ppd, "cupsModelName", NULL)) == NULL ||
(attr && attr->value == NULL))
{
ppdClose (ppd);
BUG ("ERROR: Required cupsModelName is missing in ppd file\n");
return 1;
}
memset (device_name, 0, sizeof (device_name));
strncpy (device_name, attr->value, 15);
if ((attr = ppdFindAttr (ppd, "DefaultEncoding", NULL)) == NULL ||
(attr && attr->value == NULL))
{
ppdClose (ppd);
BUG ("ERROR: Required DefaultEncoding is missing in ppd file\n");
return 1;
}
if (strstr(argv[5],"Encoding=MMR"))
{
fax_encoding = RASTER_MMR;
}
else if(strstr(argv[5],"Encoding=MH"))
{
fax_encoding = RASTER_MH;
}
else if (strstr(argv[5],"Encoding=Auto"))
{
BUG ("WARNING: AUTO is selected for Fax Encoding! Ensure this type is correct for the device");
fax_encoding = RASTER_AUTO;
}
else if (strstr(argv[5],"Encoding=TIFF"))
{
fax_encoding = RASTER_TIFF;
}
else
{
if(strcmp(attr->value,"MH") == 0) {
fax_encoding = RASTER_MH;
} else if(strcmp(attr->value,"MMR") == 0){
fax_encoding = RASTER_MMR;
}else if(strcmp(attr->value,"TIFF") ==0){
fax_encoding = RASTER_TIFF;
}else if(strcmp(attr->value,"Auto") ==0){
BUG ("WARNING: AUTO is selected for Fax Encoding! Ensure this type is correct for the device");
fax_encoding = RASTER_AUTO;
}
}
if (fax_encoding < 0) {
BUG ("ERROR: Required DefaultEncoding is invalid in ppd file\n");
return 1;
}
DBG("hpcupsfax: main: fax_encoding = %d \n", fax_encoding);
ppdClose (ppd);
if (fax_encoding == RASTER_TIFF)
{
status = ProcessTiffData(fd, fdFax, argv[2]);
} else {
cups_raster = cupsRasterOpen (fd, CUPS_RASTER_READ);
if (cups_raster == NULL)
{
status = 1;
BUG ("cupsRasterOpen failed, fd = %d\n", fd);
goto EPILOGUE;
}
status = ProcessRasterData (cups_raster, fdFax);
cupsRasterClose (cups_raster);
}
DBG("hpcupsfax: Send data to stdout \n");
status = send_data_to_stdout(fdFax);
/*********** EPILOGUE ***********/
EPILOGUE:
if (fd != 0)
{
close (fd);
}
if (fdFax > 0)
{
close (fdFax);
if (!(iLogLevel & SAVE_PCL_FILE))
{
//Retain the intermediate file only if it is needed for debugging purpose.
unlink(hpFileName);
}
}
return status;
}