1 /*****************************************************************************\
2     hpijs.cpp : HP Inkjet Server
3 
4     Copyright (c) 2001 - 2008, 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 "header.h"
41 #include "ijs.h"
42 #include "ijs_server.h"
43 #include "hpijs.h"
44 #include "services.h"
45 #include "utils.h"
46 
47 extern void SendDbusMessage (const char *dev, const char *printer, int code,
48                              const char *username, const int jobid, const char *title);
49 
50 #ifdef HAVE_LIBHPIP
51 extern  int hpijsFaxServer (int argc, char **argv);
52 #endif
53 
54 #if 0
55 int bug(const char *fmt, ...)
56 {
57    char buf[256];
58    va_list args;
59    int n;
60 
61    va_start(args, fmt);
62 
63    if ((n = vsnprintf(buf, 256, fmt, args)) == -1)
64       buf[255] = 0;     /* output was truncated */
65 
66    fprintf(stderr, buf);
67    syslog(LOG_WARNING, buf);
68 
69    fflush(stderr);
70    va_end(args);
71    return n;
72 }
73 #endif
74 
setLogLevel(UXServices * pSS,char * user_name)75 void setLogLevel(UXServices *pSS, char*user_name)
76 {
77     FILE    *fp;
78     char    str[258];
79     char    *p;
80     fp = fopen ("/usr/local/etc/cups/cupsd.conf", "r");
81     if (fp == NULL)
82         return;
83     while (!feof (fp))
84     {
85         if (!fgets (str, 256, fp))
86 	{
87 	    break;
88 	}
89 	if ((p = strstr (str, "hpLogLevel")))
90 	{
91 	    p += strlen ("hpLogLevel") + 1;
92 	    pSS->m_iLogLevel = atoi (p);
93 	    break;
94 	}
95     }
96     fclose (fp);
97 
98     if (pSS->m_iLogLevel & SAVE_PCL_FILE)
99     {
100         char    szFileName[MAX_FILE_PATH_LEN];
101         snprintf (szFileName,sizeof(szFileName), "%s/hp_%s_ijs_%d_XXXXXX", CUPS_TMP_DIR, user_name,  getpid());
102         createTempFile(szFileName, &pSS->outfp);
103 
104 //	pSS->outfp = fopen (szFileName, "w");
105 	if (pSS->outfp)
106 	{
107 	    chmod (szFileName, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
108 	}
109     }
110 }
111 
112 /* Set Print Context. */
hpijs_set_context(UXServices * pSS)113 int hpijs_set_context(UXServices *pSS)
114 {
115    int r;
116 
117    if (pSS->PenSet != DUMMY_PEN)
118    {
119      if ((r = pSS->pPC->SetPenSet((PEN_TYPE)pSS->PenSet)) != NO_ERROR)
120         BUG("unable to SetPenSet set=%d, err=%d\n", pSS->PenSet, r);
121    }
122 
123    if ((r = pSS->pPC->SelectPrintMode((QUALITY_MODE)pSS->Quality, (MEDIATYPE)pSS->MediaType, (COLORMODE)pSS->ColorMode)) !=  NO_ERROR)
124    {
125       BOOL        bDevText;
126       BUG("unable to set Quality=%d, ColorMode=%d, MediaType=%d, err=%d\n", pSS->Quality, pSS->ColorMode, pSS->MediaType, r);
127       pSS->pPC->GetPrintModeSettings((QUALITY_MODE &)pSS->Quality, (MEDIATYPE &)pSS->MediaType, (COLORMODE &)pSS->ColorMode, bDevText);
128       BUG("following will be used Quality=%d, ColorMode=%d, MediaType=%d\n", pSS->Quality, pSS->ColorMode, pSS->MediaType);
129    }
130 
131    /* Map ghostscript paper size to APDK paper size. */
132    pSS->MapPaperSize(pSS->PaperWidth, pSS->PaperHeight);
133 
134    /* Do duplex stuff now, since we have a valid print mode. */
135    if (pSS->Duplex && !pSS->Tumble)
136    {
137       if (pSS->pPC->SelectDuplexPrinting(DUPLEXMODE_BOOK) != TRUE)
138          BUG("unable to set duplex mode=book\n");
139    }
140    else if (pSS->Duplex && pSS->Tumble)
141    {
142       if (pSS->pPC->SelectDuplexPrinting(DUPLEXMODE_TABLET) != TRUE)
143          BUG("unable to set duplex mode=tablet\n");
144    }
145    else
146    {
147       pSS->pPC->SelectDuplexPrinting(DUPLEXMODE_NONE);
148    }
149 
150    if (pSS->MediaPosition != sourceTrayAuto)
151    {
152       if (pSS->pPC->SetMediaSource((MediaSource)pSS->MediaPosition) != NO_ERROR)
153          BUG("unable to set MediaPosition=%d\n", pSS->MediaPosition);
154    }
155 
156    return 0;
157 }
158 
hpijs_status_cb(void * status_cb_data,IjsServerCtx * ctx,IjsJobId job_id)159 int hpijs_status_cb(void *status_cb_data, IjsServerCtx *ctx, IjsJobId job_id)
160 {
161    return 0;
162 }
163 
hpijs_list_cb(void * list_cb_data,IjsServerCtx * ctx,IjsJobId job_id,char * val_buf,int val_size)164 int hpijs_list_cb(void *list_cb_data, IjsServerCtx *ctx, IjsJobId job_id,
165         char *val_buf, int val_size)
166 {
167    return snprintf(val_buf, val_size, "OutputFD,DeviceManufacturer,DeviceModel,PageImageFormat,Dpi,Width,Height,BitsPerSample,ColorSpace,PaperSize,PrintableArea,PrintableTopLeft,DryTime,PS:Duplex,PS:Tumble,Quality:Quality,Quality:MediaType,Quality:ColorMode,Quality:PenSet,Quality:FullBleed,PS:MediaPosition");
168 }
169 
hpijs_enum_cb(void * enum_cb_data,IjsServerCtx * ctx,IjsJobId job_id,const char * key,char * val_buf,int val_size)170 int hpijs_enum_cb(void *enum_cb_data, IjsServerCtx *ctx, IjsJobId job_id,
171        const char *key, char *val_buf, int val_size)
172 {
173    UXServices *pSS = (UXServices*)enum_cb_data;
174 
175    if (!strcmp (key, "ColorSpace"))
176    {
177       if (pSS->pPC->SupportSeparateBlack())
178          return snprintf(val_buf, val_size, "sRGB,KRGB");
179       else
180          return snprintf(val_buf, val_size, "sRGB");
181    }
182    else if (!strcmp (key, "DeviceManufacturer"))
183       return snprintf(val_buf, val_size, "HEWLETT-PACKARD,APOLLO,HP");
184    else if (!strcmp (key, "PageImageFormat"))
185       return snprintf(val_buf, val_size, "Raster");
186    else if (!strcmp (key, "BitsPerSample"))
187       return snprintf(val_buf, val_size, "8");
188    else if (!strcmp (key, "PS:Duplex"))
189    {
190       if (pSS->pPC->SelectDuplexPrinting(DUPLEXMODE_BOOK) == TRUE)
191          return snprintf(val_buf, val_size, "true");
192       else
193          return snprintf(val_buf, val_size, "false");
194       pSS->pPC->SelectDuplexPrinting(DUPLEXMODE_NONE);
195    }
196    else if (!strcmp (key, "PS:Tumble"))
197    {
198       if (pSS->pPC->SelectDuplexPrinting(DUPLEXMODE_TABLET) == TRUE)
199          return snprintf(val_buf, val_size, "true");
200       else
201          return snprintf(val_buf, val_size, "false");
202       pSS->pPC->SelectDuplexPrinting(DUPLEXMODE_NONE);
203    }
204    else
205       BUG("unable to enum key=%s\n", key);
206   return IJS_ERANGE;
207 }
208 
209 /*
210  * Set parameter (in the server) call back. Note, OutputFD is the only call that can be
211  * preceded by set DeviceManufacturer and DeviceModel.
212  */
hpijs_set_cb(void * set_cb_data,IjsServerCtx * ctx,IjsJobId job_id,const char * key,const char * value,int value_size)213 int hpijs_set_cb (void *set_cb_data, IjsServerCtx *ctx, IjsJobId job_id,
214                   const char *key, const char *value, int value_size)
215 {
216     UXServices  *pSS = (UXServices*)set_cb_data;
217     int         fd, r;
218     char        *tail;
219     int         status = 0;
220     char        svalue[IJS_MAX_PARAM+1];
221     float       w, h, dx, dy;
222     int         iVal;
223 
224     /* Sanity check input value. */
225     if (value_size > IJS_MAX_PARAM)
226     {
227         memcpy(svalue, value, IJS_MAX_PARAM);
228         svalue[IJS_MAX_PARAM] = 0;
229     }
230     else
231     {
232         memcpy(svalue, value, value_size);
233         svalue[value_size] = 0;
234     }
235 
236     if (!strcmp (key, "OutputFD"))
237     {
238         fd = strtol(svalue, &tail, 10);
239         pSS->OutputPath = fd;   /* set prn_stream as output of SS::ToDevice */
240     }
241     else if (!strcmp (key, "DeviceManufacturer"))
242     {
243         if ((strncasecmp(svalue, "HEWLETT-PACKARD", 15) != 0) &&
244             (strncasecmp(svalue, "APOLLO", 6) != 0) && (strncasecmp(svalue, "HP", 2) != 0))
245         {
246             BUG("unable to set DeviceManufacturer=%s\n", svalue);
247             status = -1;
248         }
249     }
250     else if (!strcmp (key, "DeviceModel"))
251     {
252         if ((r = pSS->pPC->SelectDevice(svalue)) != NO_ERROR)
253         {
254 	    if (r == PLUGIN_LIBRARY_MISSING)
255 	    {
256 		// call dbus here
257 		const char    *user_name = " ";
258 		const char    *title     = " ";
259                 const char *device_uri = getenv ("DEVICE_URI");
260                 const char *printer = getenv ("PRINTER");
261 		int     job_id = 0;
262 
263                 if (device_uri == NULL)
264                     device_uri = "";
265                 if (printer == NULL)
266                     printer = "";
267 
268                 SendDbusMessage (device_uri, printer,
269 	     	                 EVENT_PRINT_FAILED_MISSING_PLUGIN,
270 				 user_name, job_id, title);
271                 BUG("unable to set device=%s, err=%d\n", svalue, r);
272                 status = -1;
273 	    }
274 	    else
275 	    {
276                 /* OfficeJet LX is not very unique, do separate check here. */
277                 if (!strncmp(svalue,"OfficeJet", 10))
278                 r = pSS->pPC->SelectDevice("DESKJET 540");
279 	    }
280         }
281 
282         if (r == NO_ERROR)
283         {
284             pSS->Model = 1;
285 
286             /* Got a valid device class, let's set some print mode defaults. */
287             BOOL        bDevText;
288             pSS->pPC->GetPrintModeSettings((QUALITY_MODE &)pSS->Quality, (MEDIATYPE &)pSS->MediaType, (COLORMODE &)pSS->ColorMode, bDevText);
289         }
290         else
291         {
292             BUG("unable to set device=%s, err=%d\n", svalue, r);
293             status = -1;
294         }
295     }
296     else if ((strcmp (key, "PS:Duplex") == 0) || (strcmp (key, "Duplex") == 0))
297     {
298         if (strncmp(svalue, "true", 4) == 0)
299             pSS->Duplex = 1;
300         else
301             pSS->Duplex = 0;
302     }
303     else if ((strcmp (key, "PS:Tumble") == 0) || (strcmp (key, "Tumble") == 0))
304     {
305         if (strncmp(svalue, "true", 4) == 0)
306             pSS->Tumble = 1;
307         else
308             pSS->Tumble = 0;
309     }
310     else if (!strcmp (key, "PaperSize"))
311     {
312         w = (float)strtod(svalue, &tail);
313         h = (float)strtod(tail+1, &tail);
314 
315         if (pSS->FirstRaster)
316         {
317             /* Normal start of print Job. */
318             pSS->PaperWidth = w;
319             pSS->PaperHeight = h;
320             hpijs_set_context(pSS);
321         }
322         else
323         {
324 
325             dx = w > pSS->PaperWidth ? w - pSS->PaperWidth : pSS->PaperWidth - w;
326             dy = h > pSS->PaperHeight ? h - pSS->PaperHeight :  pSS->PaperHeight - h;
327 
328             /* Middle of print Job, ignore paper size if same. */
329             if ((dx > 0.25) || (dy > 0.25))
330             {
331                 pSS->FirstRaster = 1;  /* force new Job */
332                 pSS->PaperWidth = w;   /* set new paper size */
333                 pSS->PaperHeight = h;
334                 hpijs_set_context(pSS);
335             }
336         }
337     }
338     else if (!strcmp (key, "TopLeft"))
339     {
340         /* not currently used */
341     }
342     else if (!strcmp (key, "Quality:Quality"))
343     {
344         pSS->Quality = (QUALITY_MODE) strtol(svalue, &tail, 10);
345     }
346     else if (!strcmp (key, "Quality:MediaType"))
347     {
348         pSS->MediaType = (MEDIATYPE) strtol(svalue, &tail, 10);
349     }
350     else if (!strcmp (key, "Quality:ColorMode"))
351     {
352         pSS->ColorMode = (COLORMODE) strtol(svalue, &tail, 10);
353     }
354     else if (!strcmp (key, "Quality:PenSet"))
355     {
356         pSS->PenSet = (PEN_TYPE) strtol(svalue, &tail, 10);
357     }
358     else if (!strcmp (key, "Quality:FullBleed"))
359     {
360         pSS->FullBleed = strtol(svalue, &tail, 10);
361     }
362     else if (!strcmp (key, "PS:MediaPosition"))
363     {
364         pSS->MediaPosition = strtol(svalue, &tail, 10);
365     }
366     else if (!strcmp (key, "DryTime"))
367     {
368         iVal = strtol (svalue, &tail, 10);
369         pSS->pPC->SetPrinterHint (EXTRA_DRYTIME_HINT, iVal);
370     }
371     else if (!strcmp (key, "RedEye"))
372     {
373         iVal = strtol (svalue, &tail, 10);
374         pSS->pPC->SetPrinterHint (RED_EYE_REMOVAL_HINT, iVal);
375     }
376     else if (!strcmp (key, "PhotoFix"))
377     {
378         iVal = strtol (svalue, &tail, 10);
379         pSS->pPC->SetPrinterHint (PHOTO_FIX_HINT, iVal);
380     }
381     else if (!strcmp (key, "MaxJpegFileSize"))
382     {
383         iVal = strtol (svalue, &tail, 10);
384         pSS->pPC->SetPrinterHint (MAX_FILE_SIZE_HINT, iVal);
385     }
386     else if (!strcmp (key, "Quality:SpeedMech") && !pSS->Duplex)
387     {
388         pSS->pPC->SetPrinterHint (PAGES_IN_DOC_HINT, 512);
389 	pSS->EnableSpeedMech (TRUE);
390     }
391     else if (!strcmp (key, "Quality:MediaSubtype"))
392     {
393         iVal = strtol (svalue, &tail, 10);
394         pSS->pPC->SetMediaSubtype (iVal);
395     }
396 //  The next 5 values are passed in as inch * 1000
397     else if (!strcmp (key, "Margin:TopPadding"))
398     {
399         iVal = strtol (svalue, &tail, 10);
400         pSS->pPC->SetMechOffset (iVal);
401     }
402     else if (!strcmp (key, "Overspray:Left"))
403     {
404         iVal = strtol (svalue, &tail, 10);
405         pSS->pPC->SetPrinterHint (LEFT_OVERSPRAY_HINT, iVal);
406     }
407     else if (!strcmp (key, "Overspray:Top"))
408     {
409         iVal = strtol (svalue, &tail, 10);
410         pSS->pPC->SetPrinterHint (TOP_OVERSPRAY_HINT, iVal);
411     }
412     else if (!strcmp (key, "Overspray:Right"))
413     {
414         iVal = strtol (svalue, &tail, 10);
415         pSS->pPC->SetPrinterHint (RIGHT_OVERSPRAY_HINT, iVal);
416     }
417     else if (!strcmp (key, "Overspray:Bottom"))
418     {
419         iVal = strtol (svalue, &tail, 10);
420         pSS->pPC->SetPrinterHint (BOTTOM_OVERSPRAY_HINT, iVal);
421     }
422     else
423         BUG("unable to set key=%s, value=%s\n", key, svalue);
424 
425     return status;
426 }
427 
428 /* Get parameter (from the server) call back. Note, all calls must be preceded by set DeviceName. */
hpijs_get_cb(void * get_cb_data,IjsServerCtx * ctx,IjsJobId job_id,const char * key,char * value_buf,int value_size)429 int hpijs_get_cb(void *get_cb_data, IjsServerCtx *ctx, IjsJobId job_id, const char *key, char *value_buf, int value_size)
430 {
431    UXServices *pSS = (UXServices*)get_cb_data;
432    float        fX;
433    float        fY;
434 
435    if (!strcmp (key, "PrintableArea"))
436    {
437        fY = pSS->pPC->PrintableHeight ();
438       /* If duplexing, adjust printable height to 1/2 inch top/bottom margins, except laserjets. */
439       if ((pSS->pPC->QueryDuplexMode() != DUPLEXMODE_NONE) && pSS->pPC->RotateImageForBackPage() && (FALSE == pSS->pPC->IsBorderless()))
440       {
441           // User has requested fullbleed printing and printer supports 4-sided fullbleed or
442           // top and bottom margin are equal (0.125"), then
443           // don't need top and bottom margins to be 0.5" each. In other words, if physical page size -
444           // printable height is more than 0.25 inches, adjustment is required for symmetry.
445           // Update - 11/22/05: Not so, the autoduplexer still requires a half inch margin.
446 #if 0
447          if ((pSS->pPC->PrintableHeight () + 0.28) < pSS->pPC->PhysicalPageSizeY ())
448          {
449              fY = pSS->pPC->PhysicalPageSizeY () - 1.0;
450          }
451 #endif
452          fY = pSS->pPC->PhysicalPageSizeY () - 1.0;
453 
454          // SuperB size paper requires larger margins
455          if (pSS->pPC->PhysicalPageSizeY () > 18.0)
456          {
457              fY = 1.5;
458          }
459 
460       }
461 
462 /*
463  *      Fullbleed printing is requested and printer supports it, then
464  *      return the unadjusted physical width and height.
465  */
466 
467       if ((fX = pSS->pPC->PrintableWidth ()) > pSS->PaperWidth)
468       {
469           fX = pSS->PaperWidth;
470           fY = pSS->PaperHeight;
471       }
472 
473       return (snprintf (value_buf, value_size, "%.4fx%.4f", fX, fY));
474    }
475    else if (!strcmp (key, "PrintableTopLeft"))
476    {
477        fY = pSS->pPC->PrintableStartY ();
478       /* If duplexing, adjust printable top to 1/2 inch top margin, except laserjets. */
479       if ((pSS->pPC->QueryDuplexMode() != DUPLEXMODE_NONE) && pSS->pPC->RotateImageForBackPage() && (FALSE == pSS->pPC->IsBorderless()))
480       {
481 #if 0
482          if ((pSS->pPC->PrintableHeight () + 0.28) < pSS->pPC->PhysicalPageSizeY ())
483          {
484              fY = 0.5;
485          }
486 #endif
487          fY = 0.5;
488          // SuperB size paper requires larger margins
489          if (pSS->pPC->PhysicalPageSizeY () > 18.0)
490          {
491              fY = 0.75;
492          }
493 
494       }
495 
496       return snprintf (value_buf, value_size, "%.4fx%.4f", pSS->pPC->PrintableStartX (), fY);
497    }
498    else if ((!strcmp (key, "Duplex")) || (!strcmp (key, "PS:Duplex")))
499    {
500       if (pSS->pPC->QueryDuplexMode() == DUPLEXMODE_NONE)
501          return snprintf(value_buf, value_size, "false");
502       else
503          return snprintf(value_buf, value_size, "true");
504    }
505    else if ((!strcmp (key, "Tumble")) || (!strcmp (key, "PS:Tumble")))
506    {
507       if (pSS->pPC->QueryDuplexMode() == DUPLEXMODE_TABLET)
508          return snprintf(value_buf, value_size, "true");
509       else
510          return snprintf(value_buf, value_size, "false");
511    }
512    else if (!strcmp (key, "PaperSize"))
513    {
514       return snprintf(value_buf, value_size, "%.4fx%.4f", pSS->pPC->PhysicalPageSizeX(), pSS->pPC->PhysicalPageSizeY());
515    }
516    else if (!strcmp (key, "Dpi"))
517    {
518       return snprintf(value_buf, value_size, "%dx%d", pSS->pPC->EffectiveResolutionX(), pSS->pPC->EffectiveResolutionY());
519    }
520    else if (!strcmp (key, "DeviceModel"))
521    {
522       return snprintf(value_buf, value_size, "%s", pSS->pPC->PrinterModel());
523    }
524    else if (!strcmp (key, "Quality:Quality"))
525    {
526       return snprintf(value_buf, value_size, "%d", pSS->Quality);
527    }
528    else if (!strcmp (key, "Quality:ColorMode"))
529    {
530       return snprintf(value_buf, value_size, "%d", pSS->ColorMode);
531    }
532    else if (!strcmp (key, "Quality:MediaType"))
533    {
534       return snprintf(value_buf, value_size, "%d", pSS->MediaType);
535    }
536    else if (!strcmp (key, "ColorSpace"))
537    {
538       return snprintf(value_buf, value_size, "%s", pSS->ph.cs);
539    }
540    else if (!strcmp (key, "PageImageFormat"))
541    {
542       return snprintf(value_buf, value_size, "Raster");
543    }
544    else if (!strcmp (key, "BitsPerSample"))
545    {
546       return snprintf(value_buf, value_size, "8");
547    }
548    else if (!strcmp (key, "PS:MediaPosition"))
549    {
550       return snprintf(value_buf, value_size, "%d", pSS->MediaPosition);
551    }
552    else
553       BUG("unable to get key=%s\n", key);
554 
555    return IJS_EUNKPARAM;
556 }
557 
558 /* Get raster from the client. */
hpijs_get_client_raster(IjsServerCtx * ctx,char * buf,int size,char white)559 int hpijs_get_client_raster(IjsServerCtx *ctx, char *buf, int size, char white)
560 {
561    int status, clean=1, i;
562 
563    status = ijs_server_get_data(ctx, (char *)buf, size);
564 
565    if (status < 0)
566       return status;  /* error */
567 
568    /* Check for blank raster. */
569    for (i = 0; i < size; i++)
570    {
571       if (buf[i] != white)
572       {
573          clean = 0;
574          break;
575       }
576    }
577 
578    if (clean)
579       return 0;
580 
581    return size;
582 }
583 
main(int argc,char * argv[],char * evenp[])584 int main (int argc, char *argv[], char *evenp[])
585 {
586    UXServices *pSS = NULL;
587    IjsServerCtx *ctx = NULL;
588    char *raster = NULL, *k_raster = NULL;
589    int status = EXIT_FAILURE;
590    int ret, n, i, kn=0, width, k_width;
591    char user_name[32]={0,};
592 
593    openlog("hpijs", LOG_PID,  LOG_DAEMON);
594 
595    if (argc > 1)
596    {
597       const char *arg = argv[1];
598       if ((arg[0] == '-') && (arg[1] == 'h'))
599       {
600          fprintf(stdout, "\nHP Co. Inkjet Server %s\n", VERSION);
601          fprintf(stdout, "Copyright (c) 2001-2004, HP Co.\n");
602          exit(0);
603       }
604    }
605 
606    if (argc > 2)
607         strncpy(user_name, argv[2], sizeof(user_name));
608 
609 #ifdef HAVE_LIBHPIP
610    char *pDev;
611    if ((pDev = getenv ("DEVICE_URI")) &&
612        ((strncmp (pDev, "hpfax:", 6)) == 0))
613    {
614        exit ( hpijsFaxServer (argc, argv));
615    }
616 #endif
617 
618    ctx = ijs_server_init();
619    if (ctx == NULL)
620    {
621       BUG("unable to init hpijs server\n");
622       goto BUGOUT;
623    }
624 
625    pSS = new UXServices();
626    if (pSS->constructor_error != NO_ERROR)
627    {
628       BUG("unable to open Services object err=%d\n", pSS->constructor_error);
629       goto BUGOUT;
630    }
631 
632    setLogLevel(pSS, user_name);
633 
634 #ifdef CAPTURE
635    char szCapOutFile[MAX_FILE_PATH_LEN];
636    snprintf(szCapOutFile, sizeof(szCapOutFile),"%s/hp_%s_ijs_capout_XXXXXX",CUPS_TMP_DIR, user_name);
637    if ((pSS->InitScript(szCapOutFile, TRUE)) != NO_ERROR)
638       BUG("unable to init capture");
639 #endif
640 
641 
642    pSS->pPC = new PrintContext (pSS, 0, 0);
643 
644    /* Ignore JOB_CANCELED. This a bi-di hack that allows the job to continue even if bi-di communication failed. */
645    if (pSS->pPC->constructor_error > 0 && pSS->DisplayStatus != DISPLAY_PRINTING_CANCELED)
646    {
647       BUG("unable to open PrintContext object err=%d\n", pSS->pPC->constructor_error);
648       goto BUGOUT;
649    }
650 
651 /*
652  *  Ignore the WARN_MODE_MISMATCH warning. This will happen if we are talking to a monochrome printer.
653  *  We will select the correct printmode later.
654  */
655 
656     if (pSS->pPC->constructor_error < 0 &&
657         pSS->pPC->constructor_error != WARN_MODE_MISMATCH)
658     {
659         BUG ("WARNING: %s\n", pSS->GetDriverMessage (pSS->pPC->constructor_error));
660 		switch (pSS->pPC->constructor_error)
661 		{
662 			case WARN_LOW_INK_BOTH_PENS:
663 			case WARN_LOW_INK_BLACK:
664 			case WARN_LOW_INK_COLOR:
665 			case WARN_LOW_INK_PHOTO:
666 			case WARN_LOW_INK_GREY:
667 			case WARN_LOW_INK_BLACK_PHOTO:
668 			case WARN_LOW_INK_COLOR_PHOTO:
669 			case WARN_LOW_INK_GREY_PHOTO:
670 			case WARN_LOW_INK_COLOR_GREY:
671 			case WARN_LOW_INK_COLOR_GREY_PHOTO:
672 			case WARN_LOW_INK_COLOR_BLACK_PHOTO:
673 			case WARN_LOW_INK_CYAN:
674 			case WARN_LOW_INK_MAGENTA:
675 			case WARN_LOW_INK_YELLOW:
676 			case WARN_LOW_INK_MULTIPLE_PENS:
677                         {
678                            fputs("STATE: +marker-supply-low-warning\n", stderr);
679                            break;
680                         }
681 			default:
682                            fputs("STATE: +marker-supply-low-warning\n", stderr);
683 		}
684     }
685 
686 #if 0
687    BUG("device model=%s\n", pSS->pPC->PrinterModel());
688    BUG("device class=%s\n",  pSS->pPC->PrintertypeToString(pSS->pPC->SelectedDevice()));
689    BUG("default pen=%d\n",  pSS->pPC->GetDefaultPenSet());
690    BUG("installed pen=%d\n",  pSS->pPC->GetInstalledPens());
691 #endif
692 
693    ijs_server_install_status_cb (ctx, hpijs_status_cb, pSS);
694    ijs_server_install_list_cb (ctx, hpijs_list_cb, pSS);
695    ijs_server_install_enum_cb (ctx, hpijs_enum_cb, pSS);
696    ijs_server_install_set_cb (ctx, hpijs_set_cb, pSS);
697    ijs_server_install_get_cb (ctx, hpijs_get_cb, pSS);
698 
699    while (1)
700    {
701       if ((ret = ijs_server_get_page_header(ctx, &pSS->ph)) < 0)
702       {
703          BUG("unable to read client data err=%d\n", ret);
704          goto BUGOUT;
705       }
706 
707       if (pSS->Model == -1)
708          goto BUGOUT;      /* no device selected */
709 
710       if (ret)
711       {
712          status = 0; /* normal exit */
713          break;
714       }
715 
716       if (pSS->FirstRaster)
717       {
718           char  *pEnv = getenv ("COPY_COUNT");
719           if (pEnv)
720           {
721               i = atoi (pEnv);
722               pSS->pPC->SetCopyCount (i);
723           }
724 
725          pSS->FirstRaster = 0;
726 
727          width = (int)(pSS->ph.xres * pSS->pPC->PrintableWidth() + 0.5);
728 
729          /* Desensitize input width, may be off by one due to paper size conversions. */
730          if (pSS->ph.width < width)
731             width = pSS->ph.width;
732 
733          if ((ret = pSS->pPC->SetPixelsPerRow(width, width)) != NO_ERROR)
734          {
735             BUG("unable to SetPixelsPerRow width=%d, err=%d\n", pSS->ph.width, ret);
736          }
737 
738          /* Turn off any bi-di support. Allow bi-di for printer capabilities only. */
739 //         pSS->IOMode.bDevID = pSS->IOMode.bStatus = FALSE;
740          pSS->ResetIOMode (FALSE, FALSE);
741 
742 //       Turn off SpeedMech in duplex printing mode
743          if (pSS->Duplex)
744 	 {
745 	     pSS->EnableSpeedMech (FALSE);
746 	 }
747 
748 	 if (pSS->IsSpeedMechEnabled ())
749 	 {
750 	     pSS->InitSpeedMechBuffer ();
751 	 }
752 
753          if (pSS->pJob != NULL)
754             delete pSS->pJob;
755          pSS->pJob = new Job(pSS->pPC);
756          if (pSS->pJob->constructor_error != NO_ERROR)
757          {
758             BUG("unable to create Job object err=%d\n", pSS->pJob->constructor_error);
759             goto BUGOUT;
760          }
761 
762          if (pSS->pPC->QueryDuplexMode() != DUPLEXMODE_NONE)
763          {
764             if ((pSS->pPC->QueryDuplexMode() == DUPLEXMODE_BOOK) && pSS->pPC->RotateImageForBackPage())
765                pSS->InitDuplexBuffer();
766             pSS->BackPage = FALSE;
767          }
768 
769          pSS->KRGB=0;
770          if (strcmp(pSS->ph.cs, "KRGB") == 0)
771             pSS->KRGB=1;
772 
773 #if 0
774          BUG("papersize=%d\n", pSS->pPC->GetPaperSize());
775          BUG("width=%d, height=%d\n", pSS->ph.width, pSS->ph.height);
776          BUG("EffResX=%d, EffResY=%d, InPixelsPerRow=%d, OutPixelsPerRow=%d\n",
777             pSS->pPC->EffectiveResolutionX(), pSS->pPC->EffectiveResolutionY(),
778             pSS->pPC->InputPixelsPerRow(), pSS->pPC->OutputPixelsPerRow());
779          BUG("device=%s\n", pSS->pPC->PrinterModel());
780 #endif
781       } // pSS->FirstRaster
782 
783       if ((raster = (char *)malloc(pSS->ph.width*3)) == NULL)
784       {
785          BUG("unable to allocate raster buffer size=%d: %m\n", pSS->ph.width*3);
786          goto BUGOUT;
787       }
788 
789       k_width = (pSS->ph.width + 7) >> 3;  /* width of k plane in bytes, byte aligned */
790 
791       if ((k_raster = (char *)malloc(k_width)) == NULL)
792       {
793          BUG("unable to allocate black raster buffer size=%d: %m\n", k_width);
794          goto BUGOUT;
795       }
796       memset(k_raster, 0, k_width);
797 
798       pSS->SendPreviousPage ();
799       for (i=0; i < pSS->ph.height; i++)
800       {
801          if ((n = hpijs_get_client_raster(ctx, raster, pSS->ph.width*3, 0xff)) < 0)
802             break;    /* error */
803          if (pSS->KRGB)
804          {
805             if ((kn = hpijs_get_client_raster(ctx, k_raster, k_width, 0)) < 0)
806                break;    /* error */
807          }
808          if (n == 0 && kn == 0)
809             pSS->ProcessRaster((char *)0, (char *)0);  /* blank raster */
810          else if (kn == 0)
811             pSS->ProcessRaster(raster, (char *)0);
812          else if (n == 0)
813             pSS->ProcessRaster((char *)0, k_raster);
814          else
815             pSS->ProcessRaster(raster, k_raster);
816       }
817 
818       free(raster);
819       raster = NULL;
820       free(k_raster);
821       k_raster = NULL;
822 
823       if (pSS->pPC->QueryDuplexMode() != DUPLEXMODE_NONE)
824       {
825          if ((pSS->pPC->QueryDuplexMode() == DUPLEXMODE_BOOK) && pSS->pPC->RotateImageForBackPage() && pSS->BackPage)
826          {
827             pSS->SendBackPage();
828          }
829          pSS->BackPage = (BOOL)((int)pSS->BackPage + 1) % 2;
830       }
831 
832       pSS->pJob->NewPage();
833 
834 
835    } /* end while (1) */
836 
837    if (pSS->pPC->QueryDuplexMode() != DUPLEXMODE_NONE)
838    {
839       if (pSS->BackPage)
840       {
841          /* Send extra blank line & newpage to eject the page. (for VIP printers). */
842          /* For malibu send enough blank lines to cause at least two blank rasters in Job::sendrasters(). 5/1/03, des */
843          //         for (int i = 0; i < 201; i++)
844          for (int i = 0; i < 401; i++)
845             pSS->pJob->SendRasters((unsigned char *)0);
846          pSS->pJob->NewPage();
847       }
848    }
849 
850 BUGOUT:
851    if (pSS != NULL)
852    {
853       if (pSS->pJob != NULL)
854          delete pSS->pJob;
855       if (pSS->pPC != NULL)
856          delete pSS->pPC;
857 #ifdef CAPTURE
858       pSS->EndScript();
859 #endif
860       delete pSS;
861    }
862    if (raster != NULL)
863       free(raster);
864    if (k_raster != NULL)
865       free(k_raster);
866    if (ctx != NULL)
867       ijs_server_done(ctx);
868 
869    exit(status);
870 }
871 
872