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