1 /*****************************************************************************\
2     hpcupsfax.cpp : HP CUPS fax filter
3 
4     Copyright (c) 2001 - 2010, HP Co.
5     All rights reserved.
6 
7     Redistribution and use in source and binary forms, with or without
8     modification, are permitted provided that the following conditions
9     are met:
10     1. Redistributions of source code must retain the above copyright
11        notice, this list of conditions and the following disclaimer.
12     2. Redistributions in binary form must reproduce the above copyright
13        notice, this list of conditions and the following disclaimer in the
14        documentation and/or other materials provided with the distribution.
15     3. Neither the name of the Hewlett-Packard nor the names of its
16        contributors may be used to endorse or promote products derived
17        from this software without specific prior written permission.
18 
19     THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22     IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24     NOT LIMITED TO, PATENT INFRINGEMENT; PROCUREMENT OF SUBSTITUTE GOODS OR
25     SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27     STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
28     IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29     POSSIBILITY OF SUCH DAMAGE.
30 \*****************************************************************************/
31 
32 #include <sys/stat.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <stdarg.h>
36 #include <syslog.h>
37 #include <string.h>
38 #include <unistd.h>
39 #include <fcntl.h>
40 #include <stdint.h>
41 #include <time.h>
42 #include <sys/time.h>
43 #include <arpa/inet.h>
44 #include <math.h>
45 #include <cups/cups.h>
46 #include <cups/raster.h>
47 #include <string>
48 #ifdef FALSE
49 #undef FALSE
50 #endif
51 #ifdef TRUE
52 #undef TRUE
53 #endif
54 #include "hpip.h"
55 #include "hpcupsfax.h"
56 #include "bug.h"
57 #include "utils.h"
58 using namespace std;
59 
60 int    fax_encoding = RASTER_MMR;
61 char   device_name[16];
62 BYTE   szFileHeader[68];
63 BYTE   szPageHeader[64];
64 
65 uint32_t (*convert_endian_l)(uint32_t);
66 uint16_t (*convert_endian_s)(uint16_t);
67 
68 static int iLogLevel = 1;
69 char hpFileName[MAX_FILE_PATH_LEN] ;
70 
71 #define TIFF_HDR_SIZE 8
72 #define LITTLE_ENDIAN_MODE I
73 #define BIG_ENDIAN_MODE M
74 
75 #define DBG(args...) syslog(LOG_INFO, __FILE__ " " STRINGIZE(__LINE__) ": " args)
76 
77 // GrayLevel = (5/16)R + (9/16)G + (2/16)B
78 #define RGB2BW(r, g, b) (BYTE) (((r << 2) + r + (g << 3) + g + (b << 1)) >> 4)
79 
80 
RGB2Gray(BYTE * pRGBData,int iNumPixels,BYTE * pGData)81 void RGB2Gray (BYTE *pRGBData, int iNumPixels, BYTE *pGData)
82 {
83     int     i;
84     BYTE    *pIn = pRGBData;
85     BYTE    *pOut = pGData;
86     for (i = 0; i < iNumPixels; i++, pIn += 3)
87     {
88         *pOut++ = RGB2BW ((unsigned short) *pIn, (unsigned short) pIn[1], (unsigned short) pIn[2]);
89     }
90 }
91 
GetLogLevel()92 static void GetLogLevel ()
93 {
94     FILE    *fp;
95     char    str[258];
96     char    *p;
97     fp = fopen ("/usr/local/etc/cups/cupsd.conf", "r");
98     if (fp == NULL)
99         return;
100     while (!feof (fp))
101     {
102         if (!fgets (str, 256, fp))
103 	{
104 	    break;
105 	}
106 	if ((p = strstr (str, "hpLogLevel")))
107 	{
108 	    p += strlen ("hpLogLevel") + 1;
109 	    iLogLevel = atoi (p);
110 	    break;
111 	}
112     }
113     fclose (fp);
114 }
115 
PrintCupsHeader(cups_page_header2_t m_cupsHeader)116 void PrintCupsHeader (cups_page_header2_t m_cupsHeader)
117 {
118     if (iLogLevel == 0)
119     {
120         return;
121     }
122     BUG ("DEBUG: HPFAX - startPage...\n");
123     BUG ("DEBUG: HPFAX - MediaClass = \"%s\"\n", m_cupsHeader.MediaClass);
124     BUG ("DEBUG: HPFAX - MediaColor = \"%s\"\n", m_cupsHeader.MediaColor);
125     BUG ("DEBUG: HPFAX - MediaType = \"%s\"\n", m_cupsHeader.MediaType);
126     BUG ("DEBUG: HPFAX - OutputType = \"%s\"\n", m_cupsHeader.OutputType);
127     BUG ("DEBUG: HPFAX - AdvanceDistance = %d\n", m_cupsHeader.AdvanceDistance);
128     BUG ("DEBUG: HPFAX - AdvanceMedia = %d\n", m_cupsHeader.AdvanceMedia);
129     BUG ("DEBUG: HPFAX - Collate = %d\n", m_cupsHeader.Collate);
130     BUG ("DEBUG: HPFAX - CutMedia = %d\n", m_cupsHeader.CutMedia);
131     BUG ("DEBUG: HPFAX - Duplex = %d\n", m_cupsHeader.Duplex);
132     BUG ("DEBUG: HPFAX - HWResolution = [ %d %d ]\n", m_cupsHeader.HWResolution[0], m_cupsHeader.HWResolution[1]);
133     BUG ("DEBUG: HPFAX - ImagingBoundingBox = [ %d %d %d %d ]\n",
134                m_cupsHeader.ImagingBoundingBox[0], m_cupsHeader.ImagingBoundingBox[1],
135                m_cupsHeader.ImagingBoundingBox[2], m_cupsHeader.ImagingBoundingBox[3]);
136     BUG ("DEBUG: HPFAX - InsertSheet = %d\n", m_cupsHeader.InsertSheet);
137     BUG ("DEBUG: HPFAX - Jog = %d\n", m_cupsHeader.Jog);
138     BUG ("DEBUG: HPFAX - LeadingEdge = %d\n", m_cupsHeader.LeadingEdge);
139     BUG ("DEBUG: HPFAX - Margins = [ %d %d ]\n", m_cupsHeader.Margins[0], m_cupsHeader.Margins[1]);
140     BUG ("DEBUG: HPFAX - ManualFeed = %d\n", m_cupsHeader.ManualFeed);
141     BUG ("DEBUG: HPFAX - MediaPosition = %d\n", m_cupsHeader.MediaPosition);
142     BUG ("DEBUG: HPFAX - MediaWeight = %d\n", m_cupsHeader.MediaWeight);
143     BUG ("DEBUG: HPFAX - MirrorPrint = %d\n", m_cupsHeader.MirrorPrint);
144     BUG ("DEBUG: HPFAX - NegativePrint = %d\n", m_cupsHeader.NegativePrint);
145     BUG ("DEBUG: HPFAX - NumCopies = %d\n", m_cupsHeader.NumCopies);
146     BUG ("DEBUG: HPFAX - Orientation = %d\n", m_cupsHeader.Orientation);
147     BUG ("DEBUG: HPFAX - OutputFaceUp = %d\n", m_cupsHeader.OutputFaceUp);
148     BUG ("DEBUG: HPFAX - PageSize = [ %d %d ]\n", m_cupsHeader.PageSize[0], m_cupsHeader.PageSize[1]);
149     BUG ("DEBUG: HPFAX - Separations = %d\n", m_cupsHeader.Separations);
150     BUG ("DEBUG: HPFAX - TraySwitch = %d\n", m_cupsHeader.TraySwitch);
151     BUG ("DEBUG: HPFAX - Tumble = %d\n", m_cupsHeader.Tumble);
152     BUG ("DEBUG: HPFAX - cupsWidth = %d\n", m_cupsHeader.cupsWidth);
153     BUG ("DEBUG: HPFAX - cupsHeight = %d\n", m_cupsHeader.cupsHeight);
154     BUG ("DEBUG: HPFAX - cupsMediaType = %d\n", m_cupsHeader.cupsMediaType);
155     BUG ("DEBUG: HPFAX - cupsRowStep = %d\n", m_cupsHeader.cupsRowStep);
156     BUG ("DEBUG: HPFAX - cupsBitsPerColor = %d\n", m_cupsHeader.cupsBitsPerColor);
157     BUG ("DEBUG: HPFAX - cupsBitsPerPixel = %d\n", m_cupsHeader.cupsBitsPerPixel);
158     BUG ("DEBUG: HPFAX - cupsBytesPerLine = %d\n", m_cupsHeader.cupsBytesPerLine);
159     BUG ("DEBUG: HPFAX - cupsColorOrder = %d\n", m_cupsHeader.cupsColorOrder);
160     BUG ("DEBUG: HPFAX - cupsColorSpace = %d\n", m_cupsHeader.cupsColorSpace);
161     BUG ("DEBUG: HPFAX - cupsCompression = %d\n", m_cupsHeader.cupsCompression);
162     BUG ("DEBUG: HPFAX - cupsPageSizeName = %s\n", m_cupsHeader.cupsPageSizeName);
163 }
164 
GetPageSizeFromString(char * string)165 int GetPageSizeFromString(char *string)
166 {
167    int iPageSize = atoi(string);
168    if(iPageSize == 0)
169    {
170       if(strcmp(string,"Letter") ==0){
171          iPageSize = 1;
172       }
173       else if(strcmp(string,"A4") ==0){
174          iPageSize = 2;
175       }
176       else if(strcmp(string,"Legal") ==0){
177          iPageSize = 3;
178       }
179       else{
180          DBG("hpcupsfax: GetPageSizeFromString:Default Page Size is taken,ensure it is ok.\n");
181          iPageSize = 1;
182       }
183    }
184    DBG("hpcupsfax: GetPageSizeFromString: PageSize = %d\n",iPageSize);
185    return iPageSize;
186 }
187 
ProcessRasterData(cups_raster_t * cups_raster,int fdFax)188 int  ProcessRasterData (cups_raster_t *cups_raster, int fdFax)
189 {
190     int                status = 0;
191     unsigned int                i;
192     int                widthMMR;
193     int                iInputBufSize;
194     BYTE               *pThisScanLine;
195     LPBYTE             pbOutputBuf = NULL;
196     LPBYTE             pInputBuf = NULL;
197     IP_XFORM_SPEC      xForm[3];
198     IP_IMAGE_TRAITS    traits;
199     IP_HANDLE          hJob;
200 
201     BYTE                *p;
202     cups_page_header2_t    cups_header;
203     int                    iPageNum = 0;
204     int                    color_mode;
205     char                   *pDev;
206     unsigned    int     uiPageNum = 0;
207 
208     pDev = getenv ("DEVICE_URI");
209 
210     while (cupsRasterReadHeader2 (cups_raster, &cups_header))
211     {
212         iPageNum++;
213         if (iPageNum == 1)
214         {
215             PrintCupsHeader (cups_header);
216             color_mode = (cups_header.cupsRowStep == 0) ? HPLIPFAX_MONO : HPLIPFAX_COLOR;
217             if (color_mode == HPLIPFAX_COLOR)
218             {
219                 fax_encoding = RASTER_JPEG;
220             }
221             memset (szFileHeader, 0, sizeof (szFileHeader));
222             memcpy (szFileHeader, "hplip_g3", 8);
223             p = szFileHeader + 8;
224             *p++ = 1;                                    // Version Number
225             HPLIPPUTINT32 (p, 0); p += 4;                // Total number of pages in this job
226             HPLIPPUTINT16 (p, cups_header.HWResolution[0]); p += 2;
227             HPLIPPUTINT16 (p, cups_header.HWResolution[1]); p += 2;
228             BUG("ATOI Value  = %d",atoi (cups_header.cupsPageSizeName));
229             *p++ = GetPageSizeFromString(cups_header.cupsPageSizeName);  // Output paper size
230             *p++ = atoi (cups_header.OutputType);        // Output quality
231             *p++ = fax_encoding;                         // MH, MMR or JPEG
232             p += 4;                                      // Reserved 1
233             p += 4;                                      // Reserved 2
234             write (fdFax, szFileHeader, (p - szFileHeader));
235         }
236 
237         widthMMR = (((cups_header.cupsWidth + 7) >> 3)) << 3;
238 
239 /*
240  *      Devices in the HPFax2 category require fixed width of 2528 pixels.
241  *      Example: LaserJet 2727 MFP
242  */
243 
244         if (strcmp (device_name, "HPFax4") ==0)
245         {
246             widthMMR = 1728;
247         }
248         else if (!strcmp (device_name, "HPFax2"))
249         {
250             widthMMR = 2528;
251         }
252         iInputBufSize = widthMMR * cups_header.cupsHeight;
253 
254         pInputBuf = (LPBYTE) malloc (iInputBufSize);
255         if (pInputBuf == NULL)
256         {
257             BUG ("Unable to allocate pInputBuf, size = %d\n", iInputBufSize);
258             goto BUGOUT;
259         }
260         memset (pInputBuf, 0xFF, iInputBufSize);
261 
262         pThisScanLine = new BYTE[cups_header.cupsBytesPerLine];
263         if (pThisScanLine == NULL)
264         {
265             BUG ("Unable to allocate pThisScanLine, size = %d\n", cups_header.cupsBytesPerLine);
266             goto BUGOUT;
267         }
268 
269         for (i = 0; i < cups_header.cupsHeight; i++)
270         {
271             cupsRasterReadPixels (cups_raster, pThisScanLine, cups_header.cupsBytesPerLine);
272             RGB2Gray (pThisScanLine, cups_header.cupsWidth, pInputBuf + i * widthMMR);
273         }
274 
275         WORD         wResult;
276         DWORD        dwInputAvail;
277         DWORD        dwInputUsed;
278         DWORD        dwInputNextPos;
279         DWORD        dwOutputAvail;
280         DWORD        dwOutputUsed;
281         DWORD        dwOutputThisPos;
282         pbOutputBuf = (LPBYTE) malloc (iInputBufSize);
283         if (pbOutputBuf == NULL)
284         {
285             BUG ("unable to allocate pbOutputBuf,  buffer size = %d\n", iInputBufSize);
286             goto BUGOUT;
287         }
288         memset (pbOutputBuf, 0xFF, iInputBufSize);
289 
290         memset (xForm, 0, sizeof (xForm));
291 
292         if (color_mode == HPLIPFAX_MONO)
293         {
294             i = 0;
295             xForm[i].eXform = X_GRAY_2_BI;
296 
297             // 0   - Error diffusion
298             // >0  - Threshold value
299 
300             xForm[i].aXformInfo[IP_GRAY_2_BI_THRESHOLD].dword = 127;
301             i++;
302 
303             xForm[i].eXform = X_FAX_ENCODE;
304             if (fax_encoding== RASTER_MMR)
305             {
306                 xForm[i].aXformInfo[IP_FAX_FORMAT].dword = IP_FAX_MMR;
307             }
308             else
309             {
310                 xForm[i].aXformInfo[IP_FAX_FORMAT].dword = IP_FAX_MH;
311             }
312  /*         0 = EOLs are in data as usual; */
313  /*         1 = no EOLs in data. */
314             xForm[i].aXformInfo[IP_FAX_NO_EOLS].dword = 0;
315             xForm[i].pXform = NULL;
316             xForm[i].pfReadPeek = NULL;
317             xForm[i].pfWritePeek = NULL;
318             i++;
319 
320             wResult = ipOpen (i, xForm, 0, &hJob);
321             traits.iComponentsPerPixel = 1;
322             traits.iBitsPerPixel = 8;
323         }
324         else
325         {
326             xForm[0].eXform = X_CNV_COLOR_SPACE;
327             xForm[0].aXformInfo[IP_CNV_COLOR_SPACE_WHICH_CNV].dword = IP_CNV_SRGB_TO_YCC;
328             xForm[1].eXform = X_CNV_COLOR_SPACE;
329             xForm[1].aXformInfo[IP_CNV_COLOR_SPACE_WHICH_CNV].dword = IP_CNV_YCC_TO_CIELAB;
330             xForm[0].eXform = X_JPG_ENCODE;
331             xForm[0].aXformInfo[IP_JPG_ENCODE_FOR_COLOR_FAX].dword = 1;
332             wResult = ipOpen (1, xForm, 0, &hJob);
333             traits.iComponentsPerPixel = 3;
334             traits.iBitsPerPixel = 8;
335         }
336 
337         if (wResult != IP_DONE)
338         {
339             BUG ("ipOpen failed: wResult = %x\n", wResult);
340             goto BUGOUT;
341         }
342         traits.iPixelsPerRow = widthMMR;
343         traits.lHorizDPI     = cups_header.HWResolution[0];
344         traits.lVertDPI      = cups_header.HWResolution[1];
345         traits.lNumRows      = cups_header.cupsHeight;
346         traits.iNumPages     = 1;
347         traits.iPageNum      = 1;
348 
349         wResult = ipSetDefaultInputTraits (hJob, &traits);
350         if (wResult != IP_DONE)
351         {
352             BUG ("ipSetDefaultInputTraits failed: wResult = %x\n", wResult);
353             wResult = ipClose (hJob);
354             goto BUGOUT;
355         }
356         dwInputAvail = iInputBufSize;
357         dwOutputAvail = dwInputAvail;
358 
359         wResult = ipConvert (hJob, dwInputAvail, pInputBuf, &dwInputUsed,
360                              &dwInputNextPos, dwOutputAvail, pbOutputBuf,
361                              &dwOutputUsed, &dwOutputThisPos);
362 
363         if (wResult == IP_FATAL_ERROR)
364         {
365             BUG ("ipConvert failed, wResult = %d\n", wResult);
366             goto BUGOUT;
367         }
368         if (iLogLevel > 0)
369         {
370             BUG ("dwInputAvail = %d dwInputUsed = %d dwOutputUsed = %d\n",
371                  dwInputAvail, dwInputUsed, dwOutputUsed);
372         }
373         wResult = ipClose (hJob);
374         hJob = 0;
375 
376         uiPageNum++;
377 
378         p = szPageHeader;
379         HPLIPPUTINT32 (p, uiPageNum); p += 4;                // Current page number
380         HPLIPPUTINT32 (p, widthMMR); p += 4;                // Num of pixels per row
381         HPLIPPUTINT32 (p, cups_header.cupsHeight); p += 4;    // Num of rows in this page
382         HPLIPPUTINT32 (p, dwOutputUsed); p += 4;            // Size in bytes of encoded data
383         HPLIPPUTINT32 (p, 0); p += 4;                        // Thumbnail data size
384         HPLIPPUTINT32 (p, 0); p += 4;                        // Reserved for future use
385         write (fdFax, szPageHeader, (p - szPageHeader));
386         write (fdFax, pbOutputBuf, dwOutputUsed);
387 /*
388  *      Write the thumbnail data here
389  */
390 
391         // Send this to fax handler
392 
393         free (pbOutputBuf);
394         free (pInputBuf);
395         free (pThisScanLine);
396         pbOutputBuf = NULL;
397         pInputBuf = NULL;
398         pThisScanLine = NULL;
399 
400     } /* end while (1) */
401 
402     lseek (fdFax, 9, SEEK_SET);
403     HPLIPPUTINT32 ((szFileHeader + 9), uiPageNum);
404     write (fdFax, szFileHeader + 9, 4);
405 
406 BUGOUT:
407     if (pbOutputBuf)
408     {
409         free (pbOutputBuf);
410     }
411 
412     if (pInputBuf)
413     {
414         free (pInputBuf);
415     }
416 
417     return status;
418 }
419 
420 /*
421  * Return Zero if all the below are successful
422  * Reading from stdin into a temp file
423  * Getting the final file with HPLIP file and page headers
424  */
ProcessTiffData(int fromFD,int toFD,char * user_name)425 int ProcessTiffData(int fromFD, int toFD, char* user_name)
426 {
427     BYTE      *p;
428     int       fdTiff;
429     BYTE      pTmp[4096];
430     struct timeval tv;
431     fd_set fds;
432     int page_length;
433     unsigned int page_counter;
434     unsigned int current_ifd_start;
435     unsigned int *ifd_offset;
436     unsigned int next_ifd_offset;
437     unsigned short ifd_count;
438     bool big_endian = false;
439     int i, ret, len;
440     BYTE   szTiffHeader[TIFF_HDR_SIZE];
441     int bytes_written = 0;
442     int ret_status = 0;
443     int bytes_read = 0;
444     char hpTiffFileName[MAX_FILE_PATH_LEN];
445     long input_file_size = 0;
446     FILE* pFilePtrFax;
447     snprintf(hpTiffFileName,sizeof(hpTiffFileName), "%s/hp_%s_fax_tiffXXXXXX",CUPS_TMP_DIR,user_name);
448 
449 
450 //    fdTiff = mkstemp (hpTiffFileName);
451     fdTiff = createTempFile(hpTiffFileName, &pFilePtrFax);
452     if (fdTiff < 0)
453     {
454         BUG("ERROR: Unable to open Fax output file - %s for writing\n", hpTiffFileName);
455         return 1;
456     }
457 
458     memset (szFileHeader, 0, sizeof (szFileHeader));
459     memcpy (szFileHeader, "hplip_g3", 8);
460     p = szFileHeader + 8;
461     *p++ = 1;                                    // Version Number
462     HPLIPPUTINT32 (p, 0); p += 4;                // Total number of pages in this job
463     HPLIPPUTINT16 (p, 0); p += 2;  //HWResolution[0]
464     HPLIPPUTINT16 (p, 0); p += 2;  //HWResolution[0]
465     *p++ = atoi ("0");  // Output paper size (cupsPageSizeName)
466     *p++ = atoi ("0");        // Output quality (cups OutputType)
467     *p++ = fax_encoding;                         // MH, MMR or JPEG, TIFF
468     p += 4;                                      // Reserved 1
469     p += 4;                                      // Reserved 2
470     write (toFD, szFileHeader, (p - szFileHeader));
471 
472     FD_ZERO(&fds);
473     FD_SET(fromFD, &fds);
474     tv.tv_sec = 0;
475     tv.tv_usec = 100 * 1000; //100 ms
476     i = 0;
477 
478 
479     len = read (fromFD, pTmp, 4096);
480     if (len > 0) {
481        DBG("hpcupsfax: read %d bytes from stdin", len);
482        write (fdTiff, pTmp, len);
483        bytes_written += len;
484     } else {
485            DBG("hpcupsfax: No data was available...");
486     }
487 
488     while (i++ < 10)
489     {
490         memset (pTmp, 0, 4096);
491         ret = select(fromFD+1, &fds, NULL, NULL, &tv);
492         if (ret < 0) {
493             DBG("hpcupsfax: Timed out, Continue...");
494             continue;
495         }
496 
497         if (FD_ISSET(fromFD, &fds)) {
498            DBG("hpcupsfax: Data is available");
499            while(1) {
500               memset (pTmp, 0, 4096);
501               len = read (fromFD, pTmp, 4096);
502               DBG("hpcupsfax: read %d bytes from stdin", len);
503               if (len <= 0) {
504                   DBG("hpcupsfax: No data was available, Continue...");
505                   break; //break from inner while()
506               }
507               write (fdTiff, pTmp, len);
508               bytes_written += len;
509            }
510         }
511     }
512     DBG("hpcupsfax: total bytes written to fdTiff is  %d ", bytes_written);
513     input_file_size = bytes_written;
514 
515     ret = lseek (fdTiff, 0, SEEK_SET);
516     memset (szTiffHeader, 0, sizeof (TIFF_HDR_SIZE));
517     ret = read (fdTiff, szTiffHeader, 8);
518     DBG("hpcupsfax: read %d bytes from fdTiff", ret);
519     ifd_offset = (unsigned int *) &(szTiffHeader[4]);
520     if (szTiffHeader[0] == 'M') {
521        DBG("hpcupsfax: it is big endian");
522        big_endian = true;
523        *ifd_offset = ntohl(*ifd_offset);
524     }
525     DBG("hpcupsfax: ifd_offset is %d", *ifd_offset);
526 
527     current_ifd_start = 0;
528     page_counter = 0;
529     bytes_written = 0;
530 //WHILE
531     while(1) {
532         // Note down the number of tags
533         ret = lseek (fdTiff, *ifd_offset, SEEK_SET);
534         ret = read (fdTiff, &ifd_count, 2);
535         if (big_endian) {
536             ifd_count = ntohs(ifd_count);
537         }
538         DBG("hpcupsfax: read %d bytes from fdTiff; ifd count is %d", ret, ifd_count);
539 
540         // Read the end of IFD to check if there is another IFD following (for e.g., next page or image)
541         ret = lseek (fdTiff, (*ifd_offset+2+((ifd_count)*12)), SEEK_SET);
542         ret = read (fdTiff, &next_ifd_offset, 4);
543         if (big_endian) {
544             next_ifd_offset = ntohs(next_ifd_offset);
545         }
546         DBG("hpcupsfax: read %d bytes from fdTiff at %d; next ifd offset is %d",
547                                   ret, (*ifd_offset+2+((ifd_count)*12)), next_ifd_offset);
548 
549         // Increment the page counter
550         page_counter = page_counter + 1;
551         DBG("hpcupsfax: Current page_counter is %d", page_counter);
552 
553        // Write Tiff data for the current page (IFD)
554        page_length = next_ifd_offset-current_ifd_start;
555        DBG("hpcupsfax: page_length is %d ", page_length);
556        if (page_length <= 0) {
557            len = lseek (fdTiff, 0, SEEK_END);
558            page_length = len - current_ifd_start;
559        }
560        DBG("hpcupsfax: current_ifd_start=%d next_ifd_offset=%d total bytes are %d", current_ifd_start, next_ifd_offset, page_length);
561 
562        // Write HPLIP page header
563        p = szPageHeader;
564        HPLIPPUTINT32 (p, page_counter); p += 4;     // Current page number
565        HPLIPPUTINT32 (p, 0); p += 4;                // Num of pixels per row - It is ImageWidth for Tiff
566        HPLIPPUTINT32 (p, 0); p += 4;                // Num of rows in this page - It is ImageLength for Tiff
567        HPLIPPUTINT32 (p, page_length); p += 4;      // Size in bytes of encoded data
568        HPLIPPUTINT32 (p, 0); p += 4;                // Thumbnail data size
569        HPLIPPUTINT32 (p, 0); p += 4;                // Reserved for future use
570        ret = write (toFD, szPageHeader, (p - szPageHeader));
571 
572        ret = lseek (fdTiff, current_ifd_start, SEEK_SET);
573        while (page_length > 0) {
574             if (page_length < 4096) {
575                 len = page_length;
576             } else {
577                 len = 4096;
578             }
579             bytes_read = read (fdTiff, pTmp, len);
580             ret = write (toFD, pTmp, bytes_read);
581             page_length = page_length - ret;
582             bytes_written += ret;
583        }
584 
585        // If there is no next IFD, break from the loop. Else, continue...
586        if (bytes_written > input_file_size) {
587             BUG("Error!! Bytes written to toFD is becoming more than input file size.");
588             ret_status = -1;
589             break; // while(1) for page counting
590        }
591 
592        if (next_ifd_offset == 0) {
593             break; // while(1) for page counting
594        }
595        current_ifd_start = *ifd_offset = next_ifd_offset;
596     } // while(1) for page counting
597 
598     lseek (toFD, 9, SEEK_SET);
599     HPLIPPUTINT32 ((szFileHeader + 9), page_counter);
600     write (toFD, szFileHeader + 9, 4);
601 
602 	if (!(iLogLevel & SAVE_PCL_FILE))
603 	{
604          unlink(hpTiffFileName);
605 	}
606     return ret_status;
607 }
608 
609 
send_data_to_stdout(int fromFD)610 int send_data_to_stdout(int fromFD)
611 {
612     int     iSize, i;
613     int     len;
614     BYTE    *pTmp = NULL;
615 
616     iSize = lseek (fromFD, 0, SEEK_END);
617     lseek (fromFD, 0, SEEK_SET);
618 
619     DBG("hpcupsfax: lseek(fromFD) returned %d", iSize);
620     if (iSize > 0)
621     {
622         pTmp = (BYTE *) malloc (iSize);
623     }
624     if (pTmp == NULL)
625     {
626         iSize = 1024;
627         pTmp = (BYTE *) malloc  (iSize);
628         if (pTmp == NULL)
629         {
630           return 1;
631         }
632     }
633 
634     while ((len = read (fromFD, pTmp, iSize)) > 0)
635     {
636         write (STDOUT_FILENO, pTmp, len);
637     }
638     free (pTmp);
639 
640     return 0;
641 }
642 
main(int argc,char ** argv)643 int main (int argc, char **argv)
644 {
645     int                 status = 0;
646     int                 fd = 0;
647     int                 fdFax = -1;
648     int i = 0;
649     FILE                *pFilePtrFax;
650     cups_raster_t       *cups_raster;
651     ppd_file_t          *ppd;
652     ppd_attr_t          *attr;
653     ppd_attr_t          *compression_attr;
654 
655     /*********** PROLOGUE ***********/
656 
657     GetLogLevel();
658     openlog("hpcupsfax", LOG_PID,  LOG_DAEMON);
659 
660     if (argc < 6 || argc > 7)
661     {
662         BUG ("ERROR: %s job-id user title copies options [file]\n", *argv);
663         return 1;
664     }
665 
666     if (argc == 7)
667     {
668         if ((fd = open (argv[6], O_RDONLY)) == -1)
669         {
670             BUG ("ERROR: Unable to open raster file %s\n", argv[6]);
671             return 1;
672         }
673     }
674 
675     while (argv[i] != NULL) {
676          DBG("hpcupsfax: argv[%d] = %s\n", i, argv[i]);
677          i++;
678     }
679 
680     snprintf(hpFileName,sizeof(hpFileName),"%s/hp_%s_fax_Log_XXXXXX",CUPS_TMP_DIR, argv[2]);
681 
682 //    fdFax = mkstemp (hpFileName);
683     fdFax = createTempFile(hpFileName, &pFilePtrFax);
684     if (fdFax < 0)
685     {
686          BUG ("ERROR: Unable to open Fax output file - %s for writing\n", hpFileName);
687          return 1;
688     }
689     else
690         chmod(hpFileName, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP );
691 
692     /*********** MAIN ***********/
693 
694     ppd = ppdOpenFile (getenv ("PPD"));
695     if (ppd == NULL)
696     {
697         BUG ("ERROR: Unable to open ppd file %s\n", getenv ("PPD"));
698         return 1;
699     }
700     if ((attr = ppdFindAttr (ppd, "cupsModelName", NULL)) == NULL ||
701         (attr && attr->value == NULL))
702     {
703         ppdClose (ppd);
704         BUG ("ERROR: Required cupsModelName is missing in ppd file\n");
705         return 1;
706     }
707 
708     memset (device_name, 0, sizeof (device_name));
709     strncpy (device_name, attr->value, 15);
710 
711     if ((attr = ppdFindAttr (ppd, "DefaultEncoding", NULL)) == NULL ||
712         (attr && attr->value == NULL))
713     {
714         ppdClose (ppd);
715         BUG ("ERROR: Required DefaultEncoding is missing in ppd file\n");
716         return 1;
717     }
718     if (strstr(argv[5],"Encoding=MMR"))
719     {
720        fax_encoding = RASTER_MMR;
721     }
722     else if(strstr(argv[5],"Encoding=MH"))
723     {
724        fax_encoding = RASTER_MH;
725     }
726     else if (strstr(argv[5],"Encoding=Auto"))
727     {
728        BUG ("WARNING: AUTO is selected for Fax Encoding! Ensure this type is correct for the device");
729        fax_encoding = RASTER_AUTO;
730     }
731     else if (strstr(argv[5],"Encoding=TIFF"))
732     {
733        fax_encoding = RASTER_TIFF;
734     }
735     else
736     {
737        if(strcmp(attr->value,"MH") == 0) {
738           fax_encoding = RASTER_MH;
739        } else if(strcmp(attr->value,"MMR") == 0){
740           fax_encoding = RASTER_MMR;
741        }else if(strcmp(attr->value,"TIFF") ==0){
742           fax_encoding = RASTER_TIFF;
743        }else if(strcmp(attr->value,"Auto") ==0){
744           BUG ("WARNING: AUTO is selected for Fax Encoding! Ensure this type is correct for the device");
745           fax_encoding = RASTER_AUTO;
746        }
747     }
748     if (fax_encoding < 0) {
749         BUG ("ERROR: Required DefaultEncoding is invalid in ppd file\n");
750         return 1;
751     }
752     DBG("hpcupsfax: main: fax_encoding = %d \n", fax_encoding);
753     ppdClose (ppd);
754 
755     if (fax_encoding == RASTER_TIFF)
756     {
757         status = ProcessTiffData(fd, fdFax, argv[2]);
758     } else {
759        cups_raster = cupsRasterOpen (fd, CUPS_RASTER_READ);
760        if (cups_raster == NULL)
761        {
762            status = 1;
763            BUG ("cupsRasterOpen failed, fd = %d\n", fd);
764            goto EPILOGUE;
765        }
766 
767        status = ProcessRasterData (cups_raster, fdFax);
768 
769        cupsRasterClose (cups_raster);
770     }
771 
772     DBG("hpcupsfax: Send data to stdout \n");
773     status = send_data_to_stdout(fdFax);
774 
775     /*********** EPILOGUE ***********/
776 EPILOGUE:
777     if (fd != 0)
778     {
779         close (fd);
780     }
781 
782     if (fdFax > 0)
783     {
784         close (fdFax);
785 	if (!(iLogLevel & SAVE_PCL_FILE))
786 	{
787              //Retain the intermediate file only if it is needed for debugging purpose.
788              unlink(hpFileName);
789 	}
790     }
791 
792     return status;
793 }
794 
795