Example #1
0
ppd_attr_t *				/* O - Localized attribute or @code NULL@ if none exists */
ppdLocalizeAttr(ppd_file_t *ppd,	/* I - PPD file */
		const char *keyword,	/* I - Main keyword */
		const char *spec)	/* I - Option keyword or @code NULL@ for none */
{
  ppd_attr_t	*locattr;		/* Localized attribute */
  char		ll_CC[6];		/* Language + country locale */


 /*
  * Get the default language...
  */

  ppd_ll_CC(ll_CC, sizeof(ll_CC));

 /*
  * Find the localized attribute...
  */

  if (spec)
    locattr = _ppdLocalizedAttr(ppd, keyword, spec, ll_CC);
  else
    locattr = _ppdLocalizedAttr(ppd, "Translation", keyword, ll_CC);

  if (!locattr)
    locattr = ppdFindAttr(ppd, keyword, spec);

  return (locattr);
}
Example #2
0
const char *				/* O - Value or @code NULL@ if not found */
ppdLocalizeMarkerName(
    ppd_file_t *ppd,			/* I - PPD file */
    const char *name)			/* I - Marker name to look up */
{
  ppd_attr_t	*locattr;		/* Localized attribute */
  char		ll_CC[6];		/* Language + country locale */


 /*
  * Range check input...
  */

  if (!ppd || !name)
    return (NULL);

 /*
  * Get the default language...
  */

  ppd_ll_CC(ll_CC, sizeof(ll_CC));

 /*
  * Find the localized attribute...
  */

  if ((locattr = _ppdLocalizedAttr(ppd, "cupsMarkerName", name,
                                   ll_CC)) == NULL)
    locattr = ppdFindAttr(ppd, "cupsMarkerName", name);

  return (locattr ? locattr->text : NULL);
}
Example #3
0
static void
colord_get_qualifier_format(
    ppd_file_t *ppd,			/* I - PPD file data */
    char       *format[3])		/* I - Format tuple */
{
  const char	*tmp;			/* Temporary string */
  ppd_attr_t	*attr;			/* Profile attributes */


 /*
  * Get 1st section...
  */

  if ((attr = ppdFindAttr(ppd, "cupsICCQualifier1", NULL)) != NULL)
    tmp = attr->value;
  else if (ppdFindAttr(ppd, "DefaultColorModel", NULL))
    tmp = "ColorModel";
  else if (ppdFindAttr(ppd, "DefaultColorSpace", NULL))
    tmp = "ColorSpace";
  else
    tmp = "";

  format[0] = strdup(tmp);

 /*
  * Get 2nd section...
  */

  if ((attr = ppdFindAttr(ppd, "cupsICCQualifier2", NULL)) != NULL)
    tmp = attr->value;
  else
    tmp = "MediaType";

  format[1] = strdup(tmp);

 /*
  * Get 3rd section...
  */

  if ((attr = ppdFindAttr(ppd, "cupsICCQualifier3", NULL)) != NULL)
    tmp = attr->value;
  else
    tmp = "Resolution";

  format[2] = strdup(tmp);
}
Example #4
0
/*
 * Obtention d'une donnée du fichier PPD
 * Get a string from the PPD file
 */
PPDValue PPDFile::get(const char *name, const char *opt)
{
    ppd_attr_t *attr;
    PPDValue val;

    if (!_ppd) {
        ERRORMSG(_("Trying to read a PPD file which wasn't opened"));
        return val;
    }

    if (!opt)
        attr = ppdFindAttr(_ppd, name, NULL);
    else
        attr = ppdFindAttr(_ppd, opt, name);
    if (!attr) {
        ppd_choice_t *choice;
        choice = ppdFindMarkedChoice(_ppd, name);
        if (!choice)
            return val;
        val.set(choice->choice);
    } else
        val.set(attr->value);
    return val;
}
/* Read HPBOD attribute from PPD 
 return 1 if set as 1 */
int require_bod()
{
    int bodRequire = 0;
    ppd_attr_t  *pattr = NULL;
    ppd_file_t  *pppd = NULL;	
    pppd = ppdOpenFile(getenv("PPD"));
    if (pppd == NULL) {
        fprintf (stderr, "HP PS : ppdOpenFile failed for %s\n", getenv("PPD"));		
        return 0;
    }
	
    if (((pattr = ppdFindAttr(pppd, BOD_PPD_ATR, NULL)) != NULL) &&
        (pattr && pattr->value != NULL)) {
        bodRequire = atoi(pattr->value);
    }
    return bodRequire;
}
const char *				/* O - Device URI or @code NULL@ */
cupsBackendDeviceURI(char **argv)	/* I - Command-line arguments */
{
  const char	*device_uri,		/* Device URI */
		*auth_info_required;	/* AUTH_INFO_REQUIRED env var */
  _cups_globals_t *cg = _cupsGlobals();	/* Global info */
  int		options;		/* Resolve options */
  ppd_file_t	*ppd;			/* PPD file */
  ppd_attr_t	*ppdattr;		/* PPD attribute */


  if ((device_uri = getenv("DEVICE_URI")) == NULL)
  {
    if (!argv || !argv[0] || !strchr(argv[0], ':'))
      return (NULL);

    device_uri = argv[0];
  }

  options = _HTTP_RESOLVE_STDERR;
  if ((auth_info_required = getenv("AUTH_INFO_REQUIRED")) != NULL &&
      !strcmp(auth_info_required, "negotiate"))
    options |= _HTTP_RESOLVE_FQDN;

  if ((ppd = ppdOpenFile(getenv("PPD"))) != NULL)
  {
    if ((ppdattr = ppdFindAttr(ppd, "cupsIPPFaxOut", NULL)) != NULL &&
        !_cups_strcasecmp(ppdattr->value, "true"))
      options |= _HTTP_RESOLVE_FAXOUT;

    ppdClose(ppd);
  }

  return (_httpResolveURI(device_uri, cg->resolved_uri,
                          sizeof(cg->resolved_uri), options, NULL, NULL));
}
Example #7
0
static int				/* O - Exit status */
auto_configure(ppd_file_t *ppd,		/* I - PPD file */
               const char *user)	/* I - Printing user */
{
  int		status = 0;		/* Exit status */
  ppd_option_t	*option;		/* Current option in PPD */
  ppd_attr_t	*attr;			/* Query command attribute */
  const char	*valptr;		/* Pointer into attribute value */
  char		buffer[1024],		/* String buffer */
		*bufptr;		/* Pointer into buffer */
  ssize_t	bytes;			/* Number of bytes read */
  int		datalen;		/* Side-channel data length */


 /*
  * See if the backend supports bidirectional I/O...
  */

  datalen = 1;
  if (cupsSideChannelDoRequest(CUPS_SC_CMD_GET_BIDI, buffer, &datalen,
                               30.0) != CUPS_SC_STATUS_OK ||
      buffer[0] != CUPS_SC_BIDI_SUPPORTED)
  {
    fputs("DEBUG: Unable to auto-configure PostScript Printer - no "
          "bidirectional I/O available!\n", stderr);
    return (1);
  }

 /*
  * Put the printer in PostScript mode...
  */

  begin_ps(ppd, user);

 /*
  * (STR #4028)
  *
  * As a lot of PPDs contain bad PostScript query code, we need to prevent one
  * bad query sequence from affecting all auto-configuration.  The following
  * error handler allows us to log PostScript errors to cupsd.
  */

  puts("/cups_handleerror {\n"
       "  $error /newerror false put\n"
       "  (:PostScript error in \") print cups_query_keyword print (\": ) "
       "print\n"
       "  $error /errorname get 128 string cvs print\n"
       "  (; offending command:) print $error /command get 128 string cvs "
       "print (\n) print flush\n"
       "} bind def\n"
       "errordict /timeout {} put\n"
       "/cups_query_keyword (?Unknown) def\n");
  fflush(stdout);

 /*
  * Wait for the printer to become connected...
  */

  do
  {
    sleep(1);
    datalen = 1;
  }
  while (cupsSideChannelDoRequest(CUPS_SC_CMD_GET_CONNECTED, buffer, &datalen,
                                  5.0) == CUPS_SC_STATUS_OK && !buffer[0]);

 /*
  * Then loop through every option in the PPD file and ask for the current
  * value...
  */

  fputs("DEBUG: Auto-configuring PostScript printer...\n", stderr);

  for (option = ppdFirstOption(ppd); option; option = ppdNextOption(ppd))
  {
   /*
    * See if we have a query command for this option...
    */

    snprintf(buffer, sizeof(buffer), "?%s", option->keyword);

    if ((attr = ppdFindAttr(ppd, buffer, NULL)) == NULL || !attr->value)
    {
      fprintf(stderr, "DEBUG: Skipping %s option...\n", option->keyword);
      continue;
    }

   /*
    * Send the query code to the printer...
    */

    fprintf(stderr, "DEBUG: Querying %s...\n", option->keyword);

    for (bufptr = buffer, valptr = attr->value; *valptr; valptr ++)
    {
     /*
      * Log the query code, breaking at newlines...
      */

      if (*valptr == '\n')
      {
        *bufptr = '\0';
        fprintf(stderr, "DEBUG: %s\\n\n", buffer);
        bufptr = buffer;
      }
      else if (*valptr < ' ')
      {
        if (bufptr >= (buffer + sizeof(buffer) - 4))
        {
	  *bufptr = '\0';
	  fprintf(stderr, "DEBUG: %s\n", buffer);
	  bufptr = buffer;
        }

        if (*valptr == '\r')
        {
          *bufptr++ = '\\';
          *bufptr++ = 'r';
        }
        else if (*valptr == '\t')
        {
          *bufptr++ = '\\';
          *bufptr++ = 't';
        }
        else
        {
          *bufptr++ = '\\';
          *bufptr++ = '0' + ((*valptr / 64) & 7);
          *bufptr++ = '0' + ((*valptr / 8) & 7);
          *bufptr++ = '0' + (*valptr & 7);
        }
      }
      else
      {
        if (bufptr >= (buffer + sizeof(buffer) - 1))
        {
	  *bufptr = '\0';
	  fprintf(stderr, "DEBUG: %s\n", buffer);
	  bufptr = buffer;
        }

	*bufptr++ = *valptr;
      }
    }

    if (bufptr > buffer)
    {
      *bufptr = '\0';
      fprintf(stderr, "DEBUG: %s\n", buffer);
    }

    printf("/cups_query_keyword (?%s) def\n", option->keyword);
					/* Set keyword for error reporting */
    fputs("{ (", stdout);
    for (valptr = attr->value; *valptr; valptr ++)
    {
      if (*valptr == '(' || *valptr == ')' || *valptr == '\\')
        putchar('\\');
      putchar(*valptr);
    }
    fputs(") cvx exec } stopped { cups_handleerror } if clear\n", stdout);
    					/* Send query code */
    fflush(stdout);

    datalen = 0;
    cupsSideChannelDoRequest(CUPS_SC_CMD_DRAIN_OUTPUT, buffer, &datalen, 5.0);

   /*
    * Read the response data...
    */

    bufptr    = buffer;
    buffer[0] = '\0';
    while ((bytes = cupsBackChannelRead(bufptr, sizeof(buffer) - (size_t)(bufptr - buffer) - 1, 10.0)) > 0)
    {
     /*
      * No newline at the end? Go on reading ...
      */

      bufptr += bytes;
      *bufptr = '\0';

      if (bytes == 0 ||
          (bufptr > buffer && bufptr[-1] != '\r' && bufptr[-1] != '\n'))
	continue;

     /*
      * Trim whitespace and control characters from both ends...
      */

      bytes = bufptr - buffer;

      for (bufptr --; bufptr >= buffer; bufptr --)
        if (isspace(*bufptr & 255) || iscntrl(*bufptr & 255))
	  *bufptr = '\0';
	else
	  break;

      for (bufptr = buffer; isspace(*bufptr & 255) || iscntrl(*bufptr & 255);
	   bufptr ++);

      if (bufptr > buffer)
      {
        _cups_strcpy(buffer, bufptr);
	bufptr = buffer;
      }

      fprintf(stderr, "DEBUG: Got %d bytes.\n", (int)bytes);

     /*
      * Skip blank lines...
      */

      if (!buffer[0])
        continue;

     /*
      * Check the response...
      */

      if ((bufptr = strchr(buffer, ':')) != NULL)
      {
       /*
        * PostScript code for this option in the PPD is broken; show the
        * interpreter's error message that came back...
        */

	fprintf(stderr, "DEBUG%s\n", bufptr);
	break;
      }

     /*
      * Verify the result is a valid option choice...
      */

      if (!ppdFindChoice(option, buffer))
      {
	if (!strcasecmp(buffer, "Unknown"))
	  break;

	bufptr    = buffer;
	buffer[0] = '\0';
        continue;
      }

     /*
      * Write out the result and move on to the next option...
      */

      fprintf(stderr, "PPD: Default%s=%s\n", option->keyword, buffer);
      break;
    }

   /*
    * Printer did not answer this option's query
    */

    if (bytes <= 0)
    {
      fprintf(stderr,
	      "DEBUG: No answer to query for option %s within 10 seconds.\n",
	      option->keyword);
      status = 1;
    }
  }

 /*
  * Finish the job...
  */

  fflush(stdout);
  end_ps(ppd);

 /*
  * Return...
  */

  if (status)
    _cupsLangPrintFilter(stderr, "WARNING",
                         _("Unable to configure printer options."));

  return (0);
}
Example #8
0
int					/* O - 1 if conflicts exist, 0 otherwise */
cupsMarkOptions(
    ppd_file_t    *ppd,			/* I - PPD file */
    int           num_options,		/* I - Number of options */
    cups_option_t *options)		/* I - Options */
{
  int		i, j;			/* Looping vars */
  char		*ptr,			/* Pointer into string */
		s[255];			/* Temporary string */
  const char	*val,			/* Pointer into value */
		*media,			/* media option */
		*output_bin,		/* output-bin option */
		*page_size,		/* PageSize option */
		*ppd_keyword,		/* PPD keyword */
		*print_color_mode,	/* print-color-mode option */
		*print_quality,		/* print-quality option */
		*sides;			/* sides option */
  cups_option_t	*optptr;		/* Current option */
  ppd_attr_t	*attr;			/* PPD attribute */
  _ppd_cache_t	*cache;			/* PPD cache and mapping data */


 /*
  * Check arguments...
  */

  if (!ppd || num_options <= 0 || !options)
    return (0);

  ppd_debug_marked(ppd, "Before...");

 /*
  * Do special handling for finishings, media, output-bin, output-mode,
  * print-color-mode, print-quality, and PageSize...
  */

  media         = cupsGetOption("media", num_options, options);
  output_bin    = cupsGetOption("output-bin", num_options, options);
  page_size     = cupsGetOption("PageSize", num_options, options);
  print_quality = cupsGetOption("print-quality", num_options, options);
  sides         = cupsGetOption("sides", num_options, options);

  if ((print_color_mode = cupsGetOption("print-color-mode", num_options,
                                        options)) == NULL)
    print_color_mode = cupsGetOption("output-mode", num_options, options);

  if ((media || output_bin || print_color_mode || print_quality || sides) &&
      !ppd->cache)
  {
   /*
    * Load PPD cache and mapping data as needed...
    */

    ppd->cache = _ppdCacheCreateWithPPD(ppd);
  }

  cache = ppd->cache;

  if (media)
  {
   /*
    * Loop through the option string, separating it at commas and marking each
    * individual option as long as the corresponding PPD option (PageSize,
    * InputSlot, etc.) is not also set.
    *
    * For PageSize, we also check for an empty option value since some versions
    * of MacOS X use it to specify auto-selection of the media based solely on
    * the size.
    */

    for (val = media; *val;)
    {
     /*
      * Extract the sub-option from the string...
      */

      for (ptr = s; *val && *val != ',' && (ptr - s) < (sizeof(s) - 1);)
	*ptr++ = *val++;
      *ptr++ = '\0';

      if (*val == ',')
	val ++;

     /*
      * Mark it...
      */

      if (!page_size || !page_size[0])
      {
        if (!_cups_strncasecmp(s, "Custom.", 7) || ppdPageSize(ppd, s))
          ppd_mark_option(ppd, "PageSize", s);
        else if ((ppd_keyword = _ppdCacheGetPageSize(cache, NULL, s, NULL)) != NULL)
	  ppd_mark_option(ppd, "PageSize", ppd_keyword);
      }

      if (cache && cache->source_option &&
          !cupsGetOption(cache->source_option, num_options, options) &&
	  (ppd_keyword = _ppdCacheGetInputSlot(cache, NULL, s)) != NULL)
	ppd_mark_option(ppd, cache->source_option, ppd_keyword);

      if (!cupsGetOption("MediaType", num_options, options) &&
	  (ppd_keyword = _ppdCacheGetMediaType(cache, NULL, s)) != NULL)
	ppd_mark_option(ppd, "MediaType", ppd_keyword);
    }
  }

  if (cache)
  {
    if (!cupsGetOption("com.apple.print.DocumentTicket.PMSpoolFormat",
                       num_options, options) &&
        !cupsGetOption("APPrinterPreset", num_options, options) &&
        (print_color_mode || print_quality))
    {
     /*
      * Map output-mode and print-quality to a preset...
      */

      _pwg_print_color_mode_t	pwg_pcm;/* print-color-mode index */
      _pwg_print_quality_t	pwg_pq;	/* print-quality index */
      cups_option_t		*preset;/* Current preset option */

      if (print_color_mode && !strcmp(print_color_mode, "monochrome"))
	pwg_pcm = _PWG_PRINT_COLOR_MODE_MONOCHROME;
      else
	pwg_pcm = _PWG_PRINT_COLOR_MODE_COLOR;

      if (print_quality)
      {
	pwg_pq = atoi(print_quality) - IPP_QUALITY_DRAFT;
	if (pwg_pq < _PWG_PRINT_QUALITY_DRAFT)
	  pwg_pq = _PWG_PRINT_QUALITY_DRAFT;
	else if (pwg_pq > _PWG_PRINT_QUALITY_HIGH)
	  pwg_pq = _PWG_PRINT_QUALITY_HIGH;
      }
      else
	pwg_pq = _PWG_PRINT_QUALITY_NORMAL;

      if (cache->num_presets[pwg_pcm][pwg_pq] == 0)
      {
       /*
	* Try to find a preset that works so that we maximize the chances of us
	* getting a good print using IPP attributes.
	*/

	if (cache->num_presets[pwg_pcm][_PWG_PRINT_QUALITY_NORMAL] > 0)
	  pwg_pq = _PWG_PRINT_QUALITY_NORMAL;
	else if (cache->num_presets[_PWG_PRINT_COLOR_MODE_COLOR][pwg_pq] > 0)
	  pwg_pcm = _PWG_PRINT_COLOR_MODE_COLOR;
	else
	{
	  pwg_pq  = _PWG_PRINT_QUALITY_NORMAL;
	  pwg_pcm = _PWG_PRINT_COLOR_MODE_COLOR;
	}
      }

      if (cache->num_presets[pwg_pcm][pwg_pq] > 0)
      {
       /*
	* Copy the preset options as long as the corresponding names are not
	* already defined in the IPP request...
	*/

	for (i = cache->num_presets[pwg_pcm][pwg_pq],
		 preset = cache->presets[pwg_pcm][pwg_pq];
	     i > 0;
	     i --, preset ++)
	{
	  if (!cupsGetOption(preset->name, num_options, options))
	    ppd_mark_option(ppd, preset->name, preset->value);
	}
      }
    }

    if (output_bin && !cupsGetOption("OutputBin", num_options, options) &&
	(ppd_keyword = _ppdCacheGetOutputBin(cache, output_bin)) != NULL)
    {
     /*
      * Map output-bin to OutputBin...
      */

      ppd_mark_option(ppd, "OutputBin", ppd_keyword);
    }

    if (sides && cache->sides_option &&
        !cupsGetOption(cache->sides_option, num_options, options))
    {
     /*
      * Map sides to duplex option...
      */

      if (!strcmp(sides, "one-sided") && cache->sides_1sided)
        ppd_mark_option(ppd, cache->sides_option, cache->sides_1sided);
      else if (!strcmp(sides, "two-sided-long-edge") &&
               cache->sides_2sided_long)
        ppd_mark_option(ppd, cache->sides_option, cache->sides_2sided_long);
      else if (!strcmp(sides, "two-sided-short-edge") &&
               cache->sides_2sided_short)
        ppd_mark_option(ppd, cache->sides_option, cache->sides_2sided_short);
    }
  }

 /*
  * Mark other options...
  */

  for (i = num_options, optptr = options; i > 0; i --, optptr ++)
    if (!_cups_strcasecmp(optptr->name, "media") ||
        !_cups_strcasecmp(optptr->name, "output-bin") ||
	!_cups_strcasecmp(optptr->name, "output-mode") ||
	!_cups_strcasecmp(optptr->name, "print-quality") ||
	!_cups_strcasecmp(optptr->name, "sides"))
      continue;
    else if (!_cups_strcasecmp(optptr->name, "resolution") ||
             !_cups_strcasecmp(optptr->name, "printer-resolution"))
    {
      ppd_mark_option(ppd, "Resolution", optptr->value);
      ppd_mark_option(ppd, "SetResolution", optptr->value);
      	/* Calcomp, Linotype, QMS, Summagraphics, Tektronix, Varityper */
      ppd_mark_option(ppd, "JCLResolution", optptr->value);
      	/* HP */
      ppd_mark_option(ppd, "CNRes_PGP", optptr->value);
      	/* Canon */
    }
    else if (!_cups_strcasecmp(optptr->name, "multiple-document-handling"))
    {
      if (!cupsGetOption("Collate", num_options, options) &&
          ppdFindOption(ppd, "Collate"))
      {
        if (_cups_strcasecmp(optptr->value, "separate-documents-uncollated-copies"))
	  ppd_mark_option(ppd, "Collate", "True");
	else
	  ppd_mark_option(ppd, "Collate", "False");
      }
    }
    else if (!_cups_strcasecmp(optptr->name, "finishings"))
    {
     /*
      * Lookup cupsIPPFinishings attributes for each value...
      */

      for (ptr = optptr->value; *ptr;)
      {
       /*
        * Get the next finishings number...
	*/

        if (!isdigit(*ptr & 255))
	  break;

        if ((j = strtol(ptr, &ptr, 10)) < 3)
	  break;

       /*
        * Skip separator as needed...
	*/

        if (*ptr == ',')
	  ptr ++;

       /*
        * Look it up in the PPD file...
	*/

	sprintf(s, "%d", j);

        if ((attr = ppdFindAttr(ppd, "cupsIPPFinishings", s)) == NULL)
	  continue;

       /*
        * Apply "*Option Choice" settings from the attribute value...
	*/

        ppd_mark_choices(ppd, attr->value);
      }
    }
    else if (!_cups_strcasecmp(optptr->name, "APPrinterPreset"))
    {
     /*
      * Lookup APPrinterPreset value...
      */

      if ((attr = ppdFindAttr(ppd, "APPrinterPreset", optptr->value)) != NULL)
      {
       /*
        * Apply "*Option Choice" settings from the attribute value...
	*/

        ppd_mark_choices(ppd, attr->value);
      }
    }
    else if (!_cups_strcasecmp(optptr->name, "mirror"))
      ppd_mark_option(ppd, "MirrorPrint", optptr->value);
    else
      ppd_mark_option(ppd, optptr->name, optptr->value);

  ppd_debug_marked(ppd, "After...");

  return (ppdConflicts(ppd) > 0);
}
Example #9
0
ppd_attr_t *				/* O - Localized attribute or NULL */
_ppdLocalizedAttr(ppd_file_t *ppd,	/* I - PPD file */
		  const char *keyword,	/* I - Main keyword */
		  const char *spec,	/* I - Option keyword */
		  const char *ll_CC)	/* I - Language + country locale */
{
  char		lkeyword[PPD_MAX_NAME];	/* Localization keyword */
  ppd_attr_t	*attr;			/* Current attribute */


  DEBUG_printf(("4_ppdLocalizedAttr(ppd=%p, keyword=\"%s\", spec=\"%s\", "
                "ll_CC=\"%s\")", ppd, keyword, spec, ll_CC));

 /*
  * Look for Keyword.ll_CC, then Keyword.ll...
  */

  snprintf(lkeyword, sizeof(lkeyword), "%s.%s", ll_CC, keyword);
  if ((attr = ppdFindAttr(ppd, lkeyword, spec)) == NULL)
  {
   /*
    * <rdar://problem/22130168>
    *
    * Hong Kong locale needs special handling...  Sigh...
    */

    if (!strcmp(ll_CC, "zh_HK"))
    {
      snprintf(lkeyword, sizeof(lkeyword), "zh_TW.%s", keyword);
      attr = ppdFindAttr(ppd, lkeyword, spec);
    }

    if (!attr)
    {
      snprintf(lkeyword, sizeof(lkeyword), "%2.2s.%s", ll_CC, keyword);
      attr = ppdFindAttr(ppd, lkeyword, spec);
    }

    if (!attr)
    {
      if (!strncmp(ll_CC, "ja", 2))
      {
       /*
	* Due to a bug in the CUPS DDK 1.1.0 ppdmerge program, Japanese
	* PPD files were incorrectly assigned "jp" as the locale name
	* instead of "ja".  Support both the old (incorrect) and new
	* locale names for Japanese...
	*/

	snprintf(lkeyword, sizeof(lkeyword), "jp.%s", keyword);
	attr = ppdFindAttr(ppd, lkeyword, spec);
      }
      else if (!strncmp(ll_CC, "no", 2))
      {
       /*
	* Norway has two languages, "Bokmal" (the primary one)
	* and "Nynorsk" (new Norwegian); we map "no" to "nb" here as
	* recommended by the locale folks...
	*/

	snprintf(lkeyword, sizeof(lkeyword), "nb.%s", keyword);
	attr = ppdFindAttr(ppd, lkeyword, spec);
      }
    }
  }

#ifdef DEBUG
  if (attr)
    DEBUG_printf(("5_ppdLocalizedAttr: *%s %s/%s: \"%s\"\n", attr->name,
                  attr->spec, attr->text, attr->value ? attr->value : ""));
  else
    DEBUG_puts("5_ppdLocalizedAttr: NOT FOUND");
#endif /* DEBUG */

  return (attr);
}
Example #10
0
dt_printer_info_t *dt_get_printer_info(const char *printer_name)
{
  cups_dest_t *dests;
  int num_dests = cupsGetDests(&dests);
  cups_dest_t *dest = cupsGetDest(printer_name, NULL, num_dests, dests);
  dt_printer_info_t *result = NULL;

  if (dest)
  {
    const char *PPDFile = cupsGetPPD (printer_name);
    result = (dt_printer_info_t *)malloc(sizeof(dt_printer_info_t));
    g_strlcpy(result->name, dest->name, MAX_NAME);
    ppd_file_t *ppd = ppdOpenFile(PPDFile);

    if (ppd)
    {
      ppdMarkDefaults(ppd);
      cupsMarkOptions(ppd, dest->num_options, dest->options);

      // hardware margins

      ppd_attr_t *attr = ppdFindAttr(ppd, "HWMargins", NULL);

      if (attr)
      {
        sscanf(attr->value, "%lf %lf %lf %lf",
               &result->hw_margin_left, &result->hw_margin_bottom,
               &result->hw_margin_right, &result->hw_margin_top);

        result->hw_margin_left   = dt_pdf_point_to_mm (result->hw_margin_left);
        result->hw_margin_bottom = dt_pdf_point_to_mm (result->hw_margin_bottom);
        result->hw_margin_right  = dt_pdf_point_to_mm (result->hw_margin_right);
        result->hw_margin_top    = dt_pdf_point_to_mm (result->hw_margin_top);
      }

      // default resolution

      attr = ppdFindAttr(ppd, "DefaultResolution", NULL);

      if (attr)
      {
        char *x = strstr(attr->value, "x");

        if (x)
          sscanf (x+1, "%ddpi", &result->resolution);
        else
          sscanf (attr->value, "%ddpi", &result->resolution);
      }
      else
        result->resolution = 300;

      while(result->resolution>360)
        result->resolution /= 2.0;

      ppdClose(ppd);
      unlink(PPDFile);
    }
  }

  cupsFreeDests(num_dests, dests);
  return result;
}
Example #11
0
static void
ppd_handle_media(ppd_file_t *ppd)	/* I - PPD file */
{
  ppd_choice_t	*manual_feed,		/* ManualFeed choice, if any */
		*input_slot;		/* InputSlot choice, if any */
  ppd_size_t	*size;			/* Current media size */
  ppd_attr_t	*rpr;			/* RequiresPageRegion value */


 /*
  * This function determines what page size code to use, if any, for the
  * current media size, InputSlot, and ManualFeed selections.
  *
  * We use the PageSize code if:
  *
  * 1. A custom media size is selected.
  * 2. ManualFeed and InputSlot are not selected (or do not exist).
  * 3. ManualFeed is selected but is False and InputSlot is not selected or
  *    the selection has no code - the latter check done to support "auto" or
  *    "printer default" InputSlot options.
  *
  * We use the PageRegion code if:
  *
  * 4. RequiresPageRegion does not exist and the PPD contains cupsFilter
  *    keywords, indicating this is a CUPS-based driver.
  * 5. RequiresPageRegion exists for the selected InputSlot (or "All" for any
  *    InputSlot or ManualFeed selection) and is True.
  *
  * If none of the 5 conditions are true, no page size code is used and we
  * unmark any existing PageSize or PageRegion choices.
  */

  if ((size = ppdPageSize(ppd, NULL)) == NULL)
    return;

  manual_feed = ppdFindMarkedChoice(ppd, "ManualFeed");
  input_slot  = ppdFindMarkedChoice(ppd, "InputSlot");

  if (input_slot != NULL)
    rpr = ppdFindAttr(ppd, "RequiresPageRegion", input_slot->choice);
  else
    rpr = NULL;

  if (!rpr)
    rpr = ppdFindAttr(ppd, "RequiresPageRegion", "All");

  if (!_cups_strcasecmp(size->name, "Custom") ||
      (!manual_feed && !input_slot) ||
      (manual_feed && !_cups_strcasecmp(manual_feed->choice, "False") &&
       (!input_slot || (input_slot->code && !input_slot->code[0]))) ||
      (!rpr && ppd->num_filters > 0))
  {
   /*
    * Use PageSize code...
    */

    ppdMarkOption(ppd, "PageSize", size->name);
  }
  else if (rpr && rpr->value && !_cups_strcasecmp(rpr->value, "True"))
  {
   /*
    * Use PageRegion code...
    */

    ppdMarkOption(ppd, "PageRegion", size->name);
  }
  else
  {
   /*
    * Do not use PageSize or PageRegion code...
    */

    ppd_choice_t	*page;		/* PageSize/Region choice, if any */

    if ((page = ppdFindMarkedChoice(ppd, "PageSize")) != NULL)
    {
     /*
      * Unmark PageSize...
      */

      page->marked = 0;
      cupsArrayRemove(ppd->marked, page);
    }

    if ((page = ppdFindMarkedChoice(ppd, "PageRegion")) != NULL)
    {
     /*
      * Unmark PageRegion...
      */

      page->marked = 0;
      cupsArrayRemove(ppd->marked, page);
    }
  }
}
Example #12
0
int					/* O - 1 if custom sizes are supported, 0 otherwise */
ppdPageSizeLimits(ppd_file_t *ppd,	/* I - PPD file record */
                  ppd_size_t *minimum,	/* O - Minimum custom size */
		  ppd_size_t *maximum)	/* O - Maximum custom size */
{
  ppd_choice_t	*qualifier2,		/* Second media qualifier */
		*qualifier3;		/* Third media qualifier */
  ppd_attr_t	*attr;			/* Attribute */
  float		width,			/* Min/max width */
		length;			/* Min/max length */
  char		spec[PPD_MAX_NAME];	/* Selector for min/max */


 /*
  * Range check input...
  */

  if (!ppd || !ppd->variable_sizes || !minimum || !maximum)
  {
    if (minimum)
      memset(minimum, 0, sizeof(ppd_size_t));

    if (maximum)
      memset(maximum, 0, sizeof(ppd_size_t));

    return (0);
  }

 /*
  * See if we have the cupsMediaQualifier2 and cupsMediaQualifier3 attributes...
  */

  cupsArraySave(ppd->sorted_attrs);

  if ((attr = ppdFindAttr(ppd, "cupsMediaQualifier2", NULL)) != NULL &&
      attr->value)
    qualifier2 = ppdFindMarkedChoice(ppd, attr->value);
  else
    qualifier2 = NULL;

  if ((attr = ppdFindAttr(ppd, "cupsMediaQualifier3", NULL)) != NULL &&
      attr->value)
    qualifier3 = ppdFindMarkedChoice(ppd, attr->value);
  else
    qualifier3 = NULL;

 /*
  * Figure out the current minimum width and length...
  */

  width  = ppd->custom_min[0];
  length = ppd->custom_min[1];

  if (qualifier2)
  {
   /*
    * Try getting cupsMinSize...
    */

    if (qualifier3)
    {
      snprintf(spec, sizeof(spec), ".%s.%s", qualifier2->choice,
	       qualifier3->choice);
      attr = ppdFindAttr(ppd, "cupsMinSize", spec);
    }
    else
      attr = NULL;

    if (!attr)
    {
      snprintf(spec, sizeof(spec), ".%s.", qualifier2->choice);
      attr = ppdFindAttr(ppd, "cupsMinSize", spec);
    }

    if (!attr && qualifier3)
    {
      snprintf(spec, sizeof(spec), "..%s", qualifier3->choice);
      attr = ppdFindAttr(ppd, "cupsMinSize", spec);
    }

    if ((attr && attr->value &&
         sscanf(attr->value, "%f%f", &width, &length) != 2) || !attr)
    {
      width  = ppd->custom_min[0];
      length = ppd->custom_min[1];
    }
  }

  minimum->width  = width;
  minimum->length = length;
  minimum->left   = ppd->custom_margins[0];
  minimum->bottom = ppd->custom_margins[1];
  minimum->right  = width - ppd->custom_margins[2];
  minimum->top    = length - ppd->custom_margins[3];

 /*
  * Figure out the current maximum width and length...
  */

  width  = ppd->custom_max[0];
  length = ppd->custom_max[1];

  if (qualifier2)
  {
   /*
    * Try getting cupsMaxSize...
    */

    if (qualifier3)
    {
      snprintf(spec, sizeof(spec), ".%s.%s", qualifier2->choice,
	       qualifier3->choice);
      attr = ppdFindAttr(ppd, "cupsMaxSize", spec);
    }
    else
      attr = NULL;

    if (!attr)
    {
      snprintf(spec, sizeof(spec), ".%s.", qualifier2->choice);
      attr = ppdFindAttr(ppd, "cupsMaxSize", spec);
    }

    if (!attr && qualifier3)
    {
      snprintf(spec, sizeof(spec), "..%s", qualifier3->choice);
      attr = ppdFindAttr(ppd, "cupsMaxSize", spec);
    }

    if (!attr ||
        (attr->value && sscanf(attr->value, "%f%f", &width, &length) != 2))
    {
      width  = ppd->custom_max[0];
      length = ppd->custom_max[1];
    }
  }

  maximum->width  = width;
  maximum->length = length;
  maximum->left   = ppd->custom_margins[0];
  maximum->bottom = ppd->custom_margins[1];
  maximum->right  = width - ppd->custom_margins[2];
  maximum->top    = length - ppd->custom_margins[3];

 /*
  * Return the min and max...
  */

  cupsArrayRestore(ppd->sorted_attrs);

  return (1);
}
Example #13
0
DRIVER_ERROR HPCupsFilter::startPage (cups_page_header2_t *cups_header)
{
    DRIVER_ERROR        err = NO_ERROR;
    ppd_attr_t          *attr;
    int                 xoverspray = 120;
    int                 yoverspray = 60;

/*
 *  Check for invalid data
 */
    if (cups_header->HWResolution[0] == 100 && cups_header->HWResolution[1] == 100)
    {

/*
 *      Something went wrong, cups is defaulting to 100 dpi.
 *      Some inkjet printers do not support 100 dpi. Return error.
 */

        dbglog("ERROR: Unsupported resolution\n");
        return JOB_CANCELED;
    }

//  XOverSpray and YOverSpray are entered as fractional value * 1000

    if (((attr = ppdFindAttr(m_ppd, "HPXOverSpray", NULL)) != NULL) &&
        (attr && attr->value != NULL)) {
           xoverspray = atoi(attr->value);
    }
    if (((attr = ppdFindAttr(m_ppd, "HPYOverSpray", NULL)) != NULL) &&
        (attr && attr->value != NULL)) {
           yoverspray = atoi(attr->value);
    }

    if (m_iLogLevel & BASIC_LOG) {
        printCupsHeaderInfo(cups_header);
    }

    m_JA.quality_attributes.media_type = cups_header->cupsMediaType;
    m_JA.quality_attributes.print_quality = atoi(cups_header->OutputType);
    m_JA.quality_attributes.horizontal_resolution = cups_header->HWResolution[0];
    m_JA.quality_attributes.vertical_resolution   = cups_header->HWResolution[1];
    m_JA.quality_attributes.actual_vertical_resolution   = cups_header->HWResolution[1];

//  Get the printer's actual resolution, may be different than what is reported
    char   *p;
    if ((p = strstr (cups_header->OutputType, "_"))) {
        int    x = 0, y = 0;
        p++;
        x = atoi(p);
        while (*p && *p != 'x')
            p++;
        if (*p && *p == 'x') {
            p++;
            y = atoi(p);
        }
//      Currently, there is one printer with one printmode that supports lower y-resolution
        if (y != 0) {
            m_JA.quality_attributes.actual_vertical_resolution = y;
        }
    }
    m_JA.color_mode = cups_header->cupsRowStep;
    m_JA.media_source = cups_header->MediaPosition;

    m_JA.print_borderless = (cups_header->ImagingBoundingBox[0] == 0) ? true : false;
    if (cups_header->Duplex) {
        m_JA.e_duplex_mode  = (cups_header->Tumble == 0) ? DUPLEXMODE_BOOK : DUPLEXMODE_TABLET;
    }
    else {
        m_JA.e_duplex_mode = DUPLEXMODE_NONE;
    }
    m_JA.krgb_mode = (cups_header->cupsColorSpace == CUPS_CSPACE_RGBW) ? true : false;

    /*
     *  Cups PageSize dimensions are in PostScript units, which are 72 units to an inch
     *  and is stored as <width, height>
     *  The ImagingBoundingBox is in PostScript units and are stored as <lower_left> <upper_right>
     *  and <0, 0> is at the bottom left
     *      lower_left_x = ImagingBoundingBox[0]
     *      lower_left_y = ImagingBoundingBox[1]
     *      upper_right_x = ImagingBoundingBox[2]
     *      upper_right_y = ImagingBoundingBox[3]
     *  We require <top_left> <bottom_right> values and <0, 0> is top left
     *  So,
     *      PrintableStartX = lower_left_x
     *      PrintableStartY = PhysicalPageHeight - upper_right_y
     */

    int    horz_res = cups_header->HWResolution[0];
    int    vert_res = cups_header->HWResolution[1];
    m_JA.media_attributes.pcl_id = cups_header->cupsInteger[0];
    m_JA.media_attributes.printable_start_x = (cups_header->Margins[0] * horz_res) / 72;
    m_JA.media_attributes.printable_start_y = ((cups_header->PageSize[1] - cups_header->ImagingBoundingBox[3]) * vert_res) / 72;
    m_JA.media_attributes.horizontal_overspray = (xoverspray * horz_res) / 1000;
    m_JA.media_attributes.vertical_overspray   = (yoverspray * vert_res) / 1000;

    /*
     * Left and top overspray in dots. We haven't defined ovespray for all classes in the drv.
     * Hence using default values in the case of older classes.
     */
    m_JA.media_attributes.left_overspray = cups_header->cupsReal[0] ? (cups_header->cupsReal[0] * horz_res) : m_JA.media_attributes.horizontal_overspray / 2;
    m_JA.media_attributes.top_overspray  = cups_header->cupsReal[1] ? (cups_header->cupsReal[1] * vert_res) : m_JA.media_attributes.vertical_overspray / 2;

    if (((attr = ppdFindAttr(m_ppd, "HPMechOffset", NULL)) != NULL) &&
        (attr && attr->value != NULL)) {
        m_JA.mech_offset = atoi(attr->value);
    }

    if(cups_header->PageSize[0] > 612) // Check for B size paper. B Size paper has width > 8.5 inch (612 points)
    {
        //Check if HPMechOffsetBSize attribute is defined. If it is defined then use this offset value.
        if (((attr = ppdFindAttr(m_ppd, "HPMechOffsetBSize", NULL)) != NULL) && (attr && attr->value != NULL)) 
        {
            m_JA.mech_offset = atoi(attr->value);
        }

    }

//  Get printer platform name
    if (((attr = ppdFindAttr(m_ppd, "hpPrinterPlatform", NULL)) != NULL) && (attr->value != NULL)) {

        strncpy(m_JA.printer_platform, attr->value, sizeof(m_JA.printer_platform)-1);

        if (m_iLogLevel & BASIC_LOG) {
            dbglog("HPCUPS: found Printer Platform, it is - %s\n", attr->value);
        }	

        if (strcmp(m_JA.printer_platform, "ljzjscolor") == 0) {
            if (((attr = ppdFindAttr(m_ppd, "hpLJZjsColorVersion", NULL)) != NULL) && 
                 (attr->value != NULL)) 
            {
                 m_JA.printer_platform_version = atoi(attr->value);
            }
        }
    }

//Get Raster Preprocessing status
    if (((attr = ppdFindAttr(m_ppd, "hpReverseRasterPages", NULL)) != NULL) && 
         (attr->value != NULL)) 
    {
          m_JA.pre_process_raster = atoi(attr->value);
    }

    if (((attr = ppdFindAttr(m_ppd, "HPSPDClass", NULL)) == NULL) ||
         (attr && attr->value == NULL)) 
    {
        m_JA.HPSPDClass = 0;
    }
    else
    {
        m_JA.HPSPDClass = atoi(attr->value);
    }
    

// Get the encapsulation technology from ppd

    if (((attr = ppdFindAttr(m_ppd, "hpPrinterLanguage", NULL)) == NULL) ||
         (attr && attr->value == NULL)) 
    {
            dbglog("DEBUG: Bad PPD - hpPrinterLanguage not found\n");
            ppdClose(m_ppd);
            m_ppd = NULL;
            return SYSTEM_ERROR;
    }
    strncpy(m_JA.printer_language, attr->value, sizeof(m_JA.printer_language)-1);

    if (strcmp(m_JA.printer_language, "hbpl1") == 0) {
        m_JA.media_attributes.physical_width = cups_header->PageSize[0];
        m_JA.media_attributes.physical_height = cups_header->PageSize[1];
        m_JA.media_attributes.printable_width = ((cups_header->ImagingBoundingBox[2]-cups_header->ImagingBoundingBox[0]) * horz_res) / 72;
        m_JA.media_attributes.printable_height = ((cups_header->ImagingBoundingBox[3]-cups_header->ImagingBoundingBox[1]) * vert_res) / 72;
        strncpy(m_JA.media_attributes.PageSizeName, &cups_header->cupsString[0][0], sizeof(m_JA.media_attributes.PageSizeName));
        strncpy(m_JA.media_attributes.MediaTypeName, cups_header->MediaType, sizeof(m_JA.media_attributes.MediaTypeName));
        strncpy(m_JA.quality_attributes.hbpl1_print_quality, cups_header->OutputType, sizeof(m_JA.quality_attributes.hbpl1_print_quality));
        m_JA.color_mode = cups_header->cupsRowStep;
    }
    else {
        m_JA.media_attributes.physical_width   = (cups_header->PageSize[0] * horz_res) / 72;
        m_JA.media_attributes.physical_height  = (cups_header->PageSize[1] * vert_res) / 72;
        m_JA.media_attributes.printable_width  = cups_header->cupsWidth;
        m_JA.media_attributes.printable_height = cups_header->cupsHeight;
    }

    if (m_iLogLevel & BASIC_LOG) {
        dbglog("HPCUPS: found Printer Language, it is - %s\n", attr->value);
    }

//  Fill in the other PCL header info

    struct utsname  uts_name;
    uname(&uts_name);
    strncpy(m_JA.job_title, m_argv[3], sizeof(m_JA.job_title)-1);
    strncpy(m_JA.user_name, m_argv[2], sizeof(m_JA.user_name)-1);
    strncpy(m_JA.host_name, uts_name.nodename, sizeof(m_JA.host_name)-1);
    strncpy(m_JA.os_name, uts_name.sysname, sizeof(m_JA.os_name)-1);
    getdomainname(m_JA.domain_name, sizeof(m_JA.domain_name) - 1);
    int i = strlen(m_argv[0]) - 1;
    while (i >= 0 && m_argv[0][i] != '/') {
        i--;
    }
    snprintf(m_JA.driver_name, sizeof(m_JA.driver_name), "%s; %s", &m_argv[0][i+1], HP_FILE_VERSION_STR);
    char    *ptr = getenv("DEVICE_URI");
    i = 0;
    if (ptr) {
        while (*ptr) {
            if (*ptr == '%') {
                ptr += 3;
                m_JA.printer_name[i++] = ' ';
            }
            m_JA.printer_name[i++] = *ptr++;
        }
    }

    string strPrinterURI="" , strPrinterName= "";
    if (getenv("DEVICE_URI"))
        m_DBusComm.initDBusComm(DBUS_PATH,DBUS_INTERFACE, getenv("DEVICE_URI"), m_JA.printer_name);

    ptr = strstr(m_argv[5], "job-uuid");
    if (ptr) {
        strncpy(m_JA.uuid, ptr + strlen("job-uuid=urn:uuid:"), sizeof(m_JA.uuid)-1);
    }

    for (i = 0; i < 16; i++)
        m_JA.integer_values[i] = cups_header->cupsInteger[i];

    if (cups_header->cupsString[0]) {
        strncpy(m_JA.quality_attributes.print_mode_name, &cups_header->cupsString[0][0],
                sizeof(m_JA.quality_attributes.print_mode_name)-1);
    }

    Encapsulator *encap_interface = EncapsulatorFactory::GetEncapsulator(m_JA.printer_language);

    if ((err = m_Job.Init(m_pSys, &m_JA, encap_interface)) != NO_ERROR)
    {
        if (err == PLUGIN_LIBRARY_MISSING)
        {
            fputs ("STATE: +hplip.plugin-error\n", stderr);

            m_DBusComm.sendEvent(EVENT_PRINT_FAILED_MISSING_PLUGIN, "Plugin missing", m_JA.job_id, m_JA.user_name);

        }
        dbglog ("m_Job initialization failed with error = %d\n", err);
        ppdClose(m_ppd);
        m_ppd = NULL;
        return err;
    }

    if (m_iLogLevel & BASIC_LOG) {
        dbglog("HPCUPS: returning NO_ERROR from startPage\n");
    }

    m_pPrinterBuffer = new BYTE[cups_header->cupsWidth * 4 + 32];

    return NO_ERROR;
}
Example #14
0
int          DeviceAttributes_       ( ppd_file_t        * ppd,
                                       oyOptions_s       * options,
                                       oyConfig_s        * device,
                                       const char        * ppd_file_location )
{
    oyOption_s * o = 0;
    int error = !device;
 
    oyOption_s * value3 = oyOptions_Find( options, "device_context", oyNAME_PATTERN );
    const char * device_name = oyConfig_FindString( device, "device_name", 0 );

    if(!error)
    {
      char * manufacturer= 0,
           * model=0,
           * serial=0,
           * device_settings = 0;
      const char * system_port = 0,
                 * host = 0;
      const char * keyword = 0;
      ppd_attr_t * attrs = 0;
      int attr_n, i, j;
      char ** color_key_words = 0,
            * tmp = 0;
      int color_key_words_n = 0;

      if(!device_name && !value3 && !ppd_file_location && !ppd)
      {
        message(oyMSG_WARN, (oyStruct_s*)options, _DBG_FORMAT_
                "The \"device_name\"  and \"device_context\" is\n"
                " missed to select a appropriate device.", _DBG_ARGS_ );
        error = 1;
        return error;
      }

      if(!ppd)
      {
        message( oyMSG_DBG, (oyStruct_s*)0, _DBG_FORMAT_ "\n"
                    "No PPD obtained for ", _DBG_ARGS_, device_name );
        error = -1;
        return error;
      }

 
      manufacturer = ppd->manufacturer;
      model = ppd->modelname;
      serial = 0;                       /* Not known at this time. */
      system_port = device_name;

      host = cupsServer();
      attrs = ppdFindAttr(ppd, "cupsICCProfile", 0);

      if(attrs && attrs->text)
        device_settings = attrs->text;
 
      if(error <= 0)
      {
        size_t size = 0;
        char * data = 0;
        oyConfig_s * d = device;

        oyRankMap * rank_map = oyRankMapCopy( oyConfig_GetRankMap( device ), oyAllocateFunc_ );
        if(!rank_map)
          rank_map = oyRankMapCopy( _api8.rank_map, oyAllocateFunc_ );

        OPTIONS_ADD( oyConfig_GetOptions(d,"backend_core"), manufacturer )
        OPTIONS_ADD( oyConfig_GetOptions(d,"backend_core"), model )
        OPTIONS_ADD( oyConfig_GetOptions(d,"backend_core"), serial )
        OPTIONS_ADD( oyConfig_GetOptions(d,"backend_core"), system_port )
        OPTIONS_ADD( oyConfig_GetOptions(d,"backend_core"), host )
        OPTIONS_ADD( oyConfig_GetOptions(d,"backend_core"), device_settings )

        if (value3)
        {
          /* open the PPD data */
          if(ppd_file_location)
          {
            FILE * fp = fopen( ppd_file_location, "r" );
            size_t lsize = 0;

            /* Find the total size. */
            fseek(fp , 0, SEEK_END);
            lsize = ftell(fp);
            rewind (fp);

            /* Create buffer to read contents into a profile. */
            data = (char*) malloc (sizeof(char)*lsize + 1);
            if (data == NULL) fputs ("Unable to open PPD size.",stderr);

            size = fread( data, 1, lsize, fp);
            data[size] = 0;
          }

          if(!error && data && size)
          {           
            o = oyOption_FromRegistration(
                           CMM_BASE_REG OY_SLASH "device_context.PPD.text", 0 );
            error = !o;
            if(!error)
              error = oyOption_SetFromData( o, data, size );
          
            if(!error)
              oyOptions_MoveIn( *oyConfig_GetOptions(device,"data"), &o, -1 );
          }
        }

        /* Collect all ColorKeyWords. */
        attr_n = ppd->num_attrs;

        for(i = 0; i < attr_n; i++)
        {
          char key[16];

          keyword = ppd->attrs[i]->name;

          /* we support keys beginning with ColorKeyWords, e.g.
             "ColorKeyWords" "ColorKeyWords" ... */
          snprintf( &key[0], 16, "%s", keyword );
          key[14] = 0;
        
          if (strcmp(key, "ColorKeyWords") == 0)
          {
            if( tmp && tmp[oyStrlen_(tmp) - 1] != ';' )
              STRING_ADD( tmp, ";" );
            STRING_ADD( tmp, ppd->attrs[i]->value );
          }
        }

        if(tmp)
        {
          color_key_words = oyStringSplit( tmp, ';', &color_key_words_n,
                                             oyAllocateFunc_);
          oyDeAllocateFunc_( tmp ); tmp = 0;
        }

        /* add the key/value pairs to the devices backend_core options. */
        for(j = 0; j < color_key_words_n; ++j)
        {
          const char * keyword = color_key_words[j],
                     * value = NULL;
          ppd_choice_t * c = ppdFindMarkedChoice( ppd, keyword );
          ppd_option_t * o = ppdFindOption( ppd, keyword );
                char * reg_name = 0;
          /* take the marked choice */
          if(c)
            value = c->choice;
          /* fall back to a default */
          else if(o)
            value = o->defchoice;
          else
          /* Scan PPD attributes for matching the ColorKeyWords and */
            for(i = 0; i < attr_n; i++)
              if(oyStrcmp_( ppd->attrs[i]->name, keyword ) == 0)
                value = ppd->attrs[i]->value;

          STRING_ADD( reg_name, CMM_BASE_REG OY_SLASH );
          STRING_ADD( reg_name, keyword );
          if(value)
          {
            error= oyOptions_SetFromText( oyConfig_GetOptions(d,"backend_core"),
                                               reg_name,
                                               value,
                                               OY_CREATE_NEW );
            oyRankMapAppend( &rank_map, reg_name, 2, -2, 0, 0,0 );
          }
          if(reg_name) oyDeAllocateFunc_( reg_name ); reg_name = 0;
        }

        if( color_key_words && color_key_words_n)
          oyStringListRelease_( &color_key_words, color_key_words_n,
                                oyDeAllocateFunc_ );
        else
        {
          ppd_option_t * o;
          while((o = ppdNextOption(ppd)) != 0)
          {
            const char * value = 0;
            char * reg_name = 0;

            keyword = o->keyword;
            STRING_ADD( reg_name, CMM_BASE_REG OY_SLASH );
            STRING_ADD( reg_name, keyword );
            /* take the marked choice */
            for(i = 0; i < o->num_choices; ++i)
              if(o->choices[i].marked)
              {
                value = o->choices[i].choice;
                break;
              }
            if(!value)
              value = o->defchoice;
            
            if(value)
            {
              error = oyOptions_SetFromText( oyConfig_GetOptions(d,"backend_core"),
                                                reg_name,
                                                value,
                                                OY_CREATE_NEW );
              oyRankMapAppend( &rank_map, reg_name, 2, -2, 0, 0,0 );
            }
            if(reg_name) oyDeAllocateFunc_( reg_name ); reg_name = 0;
          }
        }

        oyConfig_SetRankMap( device, rank_map );
        oyRankMapRelease( &rank_map, oyDeAllocateFunc_ );
      }
int					/* O - Exit status */
main(int  argc,				/* I - Number of command-line args */
     char *argv[])			/* I - Command-line arguments */
{
  int			fd;		/* Raster file */
  cups_raster_t		*inras,		/* Input raster stream */
			*outras;	/* Output raster stream */
  cups_page_header2_t	inheader,	/* Input raster page header */
			outheader;	/* Output raster page header */
  int			y;		/* Current line */
  unsigned char		*line;		/* Line buffer */
  int			page = 0,	/* Current page */
			page_width,	/* Actual page width */
			page_height,	/* Actual page height */
			page_top,	/* Top margin */
			page_bottom,	/* Bottom margin */
			page_left,	/* Left margin */
			linesize,	/* Bytes per line */
			lineoffset;	/* Offset into line */
  unsigned char		white;		/* White pixel */
  ppd_file_t		*ppd;		/* PPD file */
  ppd_attr_t		*back;		/* cupsBackSize attribute */
  _ppd_cache_t		*cache;		/* PPD cache */
  _pwg_size_t		*pwg_size;	/* PWG media size */
  _pwg_media_t		*pwg_media;	/* PWG media name */
  int	 		num_options;	/* Number of options */
  cups_option_t		*options = NULL;/* Options */
  const char		*val;		/* Option value */


  if (argc < 6 || argc > 7)
  {
    puts("Usage: rastertopwg job user title copies options [filename]");
    return (1);
  }
  else if (argc == 7)
  {
    if ((fd = open(argv[6], O_RDONLY)) < 0)
    {
      perror("ERROR: Unable to open print file");
      return (1);
    }
  }
  else
    fd = 0;

  inras  = cupsRasterOpen(fd, CUPS_RASTER_READ);
  outras = cupsRasterOpen(1, CUPS_RASTER_WRITE_PWG);

  ppd   = ppdOpenFile(getenv("PPD"));
  back  = ppdFindAttr(ppd, "cupsBackSide", NULL);

  num_options = cupsParseOptions(argv[5], 0, &options);

  ppdMarkDefaults(ppd);
  cupsMarkOptions(ppd, num_options, options);

  cache = ppd ? ppd->cache : NULL;

  while (cupsRasterReadHeader2(inras, &inheader))
  {
   /*
    * Compute the real raster size...
    */

    page ++;

    fprintf(stderr, "PAGE: %d %d\n", page, inheader.NumCopies);

    page_width  = (int)(inheader.cupsPageSize[0] * inheader.HWResolution[0] /
                        72.0);
    page_height = (int)(inheader.cupsPageSize[1] * inheader.HWResolution[1] /
                        72.0);
    page_left   = (int)(inheader.cupsImagingBBox[0] *
                        inheader.HWResolution[0] / 72.0);
    page_bottom = (int)(inheader.cupsImagingBBox[1] *
                        inheader.HWResolution[1] / 72.0);
    page_top    = page_height - page_bottom - inheader.cupsHeight;
    linesize    = (page_width * inheader.cupsBitsPerPixel + 7) / 8;
    lineoffset  = page_left * inheader.cupsBitsPerPixel / 8; /* Round down */

    switch (inheader.cupsColorSpace)
    {
      case CUPS_CSPACE_W :
      case CUPS_CSPACE_RGB :
      case CUPS_CSPACE_SW :
      case CUPS_CSPACE_SRGB :
      case CUPS_CSPACE_ADOBERGB :
          white = 255;
	  break;

      case CUPS_CSPACE_K :
      case CUPS_CSPACE_CMYK :
      case CUPS_CSPACE_DEVICE1 :
      case CUPS_CSPACE_DEVICE2 :
      case CUPS_CSPACE_DEVICE3 :
      case CUPS_CSPACE_DEVICE4 :
      case CUPS_CSPACE_DEVICE5 :
      case CUPS_CSPACE_DEVICE6 :
      case CUPS_CSPACE_DEVICE7 :
      case CUPS_CSPACE_DEVICE8 :
      case CUPS_CSPACE_DEVICE9 :
      case CUPS_CSPACE_DEVICEA :
      case CUPS_CSPACE_DEVICEB :
      case CUPS_CSPACE_DEVICEC :
      case CUPS_CSPACE_DEVICED :
      case CUPS_CSPACE_DEVICEE :
      case CUPS_CSPACE_DEVICEF :
          white = 0;
	  break;

      default :
	  _cupsLangPrintFilter(stderr, "ERROR", _("Unsupported raster data."));
	  fprintf(stderr, "DEBUG: Unsupported cupsColorSpace %d on page %d.\n",
	          inheader.cupsColorSpace, page);
	  return (1);
    }

    if (inheader.cupsColorOrder != CUPS_ORDER_CHUNKED)
    {
      _cupsLangPrintFilter(stderr, "ERROR", _("Unsupported raster data."));
      fprintf(stderr, "DEBUG: Unsupported cupsColorOrder %d on page %d.\n",
              inheader.cupsColorOrder, page);
      return (1);
    }

    if (inheader.cupsBitsPerPixel != 1 &&
        inheader.cupsBitsPerColor != 8 && inheader.cupsBitsPerColor != 16)
    {
      _cupsLangPrintFilter(stderr, "ERROR", _("Unsupported raster data."));
      fprintf(stderr, "DEBUG: Unsupported cupsBitsPerColor %d on page %d.\n",
              inheader.cupsBitsPerColor, page);
      return (1);
    }

    memcpy(&outheader, &inheader, sizeof(outheader));
    outheader.cupsWidth        = page_width;
    outheader.cupsHeight       = page_height;
    outheader.cupsBytesPerLine = linesize;

    outheader.cupsInteger[14]  = 0;	/* VendorIdentifier */
    outheader.cupsInteger[15]  = 0;	/* VendorLength */

    if ((val = cupsGetOption("print-content-optimize", num_options,
                             options)) != NULL)
    {
      if (!strcmp(val, "automatic"))
        strlcpy(outheader.OutputType, "Automatic",
                sizeof(outheader.OutputType));
      else if (!strcmp(val, "graphics"))
        strlcpy(outheader.OutputType, "Graphics", sizeof(outheader.OutputType));
      else if (!strcmp(val, "photo"))
        strlcpy(outheader.OutputType, "Photo", sizeof(outheader.OutputType));
      else if (!strcmp(val, "text"))
        strlcpy(outheader.OutputType, "Text", sizeof(outheader.OutputType));
      else if (!strcmp(val, "text-and-graphics"))
        strlcpy(outheader.OutputType, "TextAndGraphics",
                sizeof(outheader.OutputType));
      else
      {
        fprintf(stderr, "DEBUG: Unsupported print-content-type \"%s\".\n", val);
        outheader.OutputType[0] = '\0';
      }
    }

    if ((val = cupsGetOption("print-quality", num_options, options)) != NULL)
    {
      int quality = atoi(val);		/* print-quality value */

      if (quality >= IPP_QUALITY_DRAFT && quality <= IPP_QUALITY_HIGH)
	outheader.cupsInteger[8] = quality;
      else
      {
	fprintf(stderr, "DEBUG: Unsupported print-quality %d.\n", quality);
	outheader.cupsInteger[8] = 0;
      }
    }

    if ((val = cupsGetOption("print-rendering-intent", num_options,
                             options)) != NULL)
    {
      if (!strcmp(val, "absolute"))
        strlcpy(outheader.cupsRenderingIntent, "Absolute",
                sizeof(outheader.cupsRenderingIntent));
      else if (!strcmp(val, "automatic"))
        strlcpy(outheader.cupsRenderingIntent, "Automatic",
                sizeof(outheader.cupsRenderingIntent));
      else if (!strcmp(val, "perceptual"))
        strlcpy(outheader.cupsRenderingIntent, "Perceptual",
                sizeof(outheader.cupsRenderingIntent));
      else if (!strcmp(val, "relative"))
        strlcpy(outheader.cupsRenderingIntent, "Relative",
                sizeof(outheader.cupsRenderingIntent));
      else if (!strcmp(val, "relative-bpc"))
        strlcpy(outheader.cupsRenderingIntent, "RelativeBpc",
                sizeof(outheader.cupsRenderingIntent));
      else if (!strcmp(val, "saturation"))
        strlcpy(outheader.cupsRenderingIntent, "Saturation",
                sizeof(outheader.cupsRenderingIntent));
      else
      {
        fprintf(stderr, "DEBUG: Unsupported print-rendering-intent \"%s\".\n",
                val);
        outheader.cupsRenderingIntent[0] = '\0';
      }
    }

    if (inheader.cupsPageSizeName[0] &&
        (pwg_size = _ppdCacheGetSize(cache, inheader.cupsPageSizeName)) != NULL)
    {
      strlcpy(outheader.cupsPageSizeName, pwg_size->map.pwg,
	      sizeof(outheader.cupsPageSizeName));
    }
    else
    {
      pwg_media = _pwgMediaForSize((int)(2540.0 * inheader.cupsPageSize[0] /
                                         72.0),
                                   (int)(2540.0 * inheader.cupsPageSize[1] /
                                         72.0));

      if (pwg_media)
        strlcpy(outheader.cupsPageSizeName, pwg_media->pwg,
                sizeof(outheader.cupsPageSizeName));
      else
      {
        fprintf(stderr, "DEBUG: Unsupported PageSize %.2fx%.2f.\n",
                inheader.cupsPageSize[0], inheader.cupsPageSize[1]);
        outheader.cupsPageSizeName[0] = '\0';
      }
    }

    if (inheader.Duplex && !(page & 1) &&
        back && _cups_strcasecmp(back->value, "Normal"))
    {
      if (_cups_strcasecmp(back->value, "Flipped"))
      {
        if (inheader.Tumble)
        {
	  outheader.cupsInteger[1] = -1;/* CrossFeedTransform */
	  outheader.cupsInteger[2] = 1;	/* FeedTransform */

	  outheader.cupsInteger[3] = page_width - page_left -
	                             inheader.cupsWidth;
					/* ImageBoxLeft */
	  outheader.cupsInteger[4] = page_top;
					/* ImageBoxTop */
	  outheader.cupsInteger[5] = page_width - page_left;
      					/* ImageBoxRight */
	  outheader.cupsInteger[6] = page_height - page_bottom;
      					/* ImageBoxBottom */
        }
        else
        {
	  outheader.cupsInteger[1] = 1;	/* CrossFeedTransform */
	  outheader.cupsInteger[2] = -1;/* FeedTransform */

	  outheader.cupsInteger[3] = page_left;
					/* ImageBoxLeft */
	  outheader.cupsInteger[4] = page_bottom;
					/* ImageBoxTop */
	  outheader.cupsInteger[5] = page_left + inheader.cupsWidth;
      					/* ImageBoxRight */
	  outheader.cupsInteger[6] = page_height - page_top;
      					/* ImageBoxBottom */
        }
      }
      else if (_cups_strcasecmp(back->value, "ManualTumble"))
      {
        if (inheader.Tumble)
        {
	  outheader.cupsInteger[1] = -1;/* CrossFeedTransform */
	  outheader.cupsInteger[2] = -1;/* FeedTransform */

	  outheader.cupsInteger[3] = page_width - page_left -
	                             inheader.cupsWidth;
					/* ImageBoxLeft */
	  outheader.cupsInteger[4] = page_bottom;
					/* ImageBoxTop */
	  outheader.cupsInteger[5] = page_width - page_left;
      					/* ImageBoxRight */
	  outheader.cupsInteger[6] = page_height - page_top;
      					/* ImageBoxBottom */
        }
        else
        {
	  outheader.cupsInteger[1] = 1;	/* CrossFeedTransform */
	  outheader.cupsInteger[2] = 1;	/* FeedTransform */

	  outheader.cupsInteger[3] = page_left;
					/* ImageBoxLeft */
	  outheader.cupsInteger[4] = page_top;
					/* ImageBoxTop */
	  outheader.cupsInteger[5] = page_left + inheader.cupsWidth;
      					/* ImageBoxRight */
	  outheader.cupsInteger[6] = page_height - page_bottom;
      					/* ImageBoxBottom */
        }
      }
      else if (_cups_strcasecmp(back->value, "Rotated"))
      {
        if (inheader.Tumble)
        {
	  outheader.cupsInteger[1] = -1;/* CrossFeedTransform */
	  outheader.cupsInteger[2] = -1;/* FeedTransform */

	  outheader.cupsInteger[3] = page_width - page_left -
	                             inheader.cupsWidth;
					/* ImageBoxLeft */
	  outheader.cupsInteger[4] = page_bottom;
					/* ImageBoxTop */
	  outheader.cupsInteger[5] = page_width - page_left;
      					/* ImageBoxRight */
	  outheader.cupsInteger[6] = page_height - page_top;
      					/* ImageBoxBottom */
        }
        else
        {
	  outheader.cupsInteger[1] = 1;	/* CrossFeedTransform */
	  outheader.cupsInteger[2] = 1;	/* FeedTransform */

	  outheader.cupsInteger[3] = page_left;
					/* ImageBoxLeft */
	  outheader.cupsInteger[4] = page_top;
					/* ImageBoxTop */
	  outheader.cupsInteger[5] = page_left + inheader.cupsWidth;
      					/* ImageBoxRight */
	  outheader.cupsInteger[6] = page_height - page_bottom;
      					/* ImageBoxBottom */
        }
      }
      else
      {
       /*
        * Unsupported value...
        */

        fprintf(stderr, "DEBUG: Unsupported cupsBackSide \"%s\".\n", back->value);

	outheader.cupsInteger[1] = 1;	/* CrossFeedTransform */
	outheader.cupsInteger[2] = 1;	/* FeedTransform */

	outheader.cupsInteger[3] = page_left;
					/* ImageBoxLeft */
	outheader.cupsInteger[4] = page_top;
					/* ImageBoxTop */
	outheader.cupsInteger[5] = page_left + inheader.cupsWidth;
      					/* ImageBoxRight */
	outheader.cupsInteger[6] = page_height - page_bottom;
      					/* ImageBoxBottom */
      }
    }
    else
    {
      outheader.cupsInteger[1] = 1;	/* CrossFeedTransform */
      outheader.cupsInteger[2] = 1;	/* FeedTransform */

      outheader.cupsInteger[3] = page_left;
					/* ImageBoxLeft */
      outheader.cupsInteger[4] = page_top;
					/* ImageBoxTop */
      outheader.cupsInteger[5] = page_left + inheader.cupsWidth;
      					/* ImageBoxRight */
      outheader.cupsInteger[6] = page_height - page_bottom;
      					/* ImageBoxBottom */
    }

    if (!cupsRasterWriteHeader2(outras, &outheader))
    {
      _cupsLangPrintFilter(stderr, "ERROR", _("Error sending raster data."));
      fprintf(stderr, "DEBUG: Unable to write header for page %d.\n", page);
      return (1);
    }

   /*
    * Copy raster data...
    */

    line = malloc(linesize);

    memset(line, white, linesize);
    for (y = page_top; y > 0; y --)
      if (!cupsRasterWritePixels(outras, line, outheader.cupsBytesPerLine))
      {
	_cupsLangPrintFilter(stderr, "ERROR", _("Error sending raster data."));
	fprintf(stderr, "DEBUG: Unable to write line %d for page %d.\n",
	        page_top - y + 1, page);
	return (1);
      }

    for (y = inheader.cupsHeight; y > 0; y --)
    {
      cupsRasterReadPixels(inras, line + lineoffset, inheader.cupsBytesPerLine);
      if (!cupsRasterWritePixels(outras, line, outheader.cupsBytesPerLine))
      {
	_cupsLangPrintFilter(stderr, "ERROR", _("Error sending raster data."));
	fprintf(stderr, "DEBUG: Unable to write line %d for page %d.\n",
	        inheader.cupsHeight - y + page_top + 1, page);
	return (1);
      }
    }

    memset(line, white, linesize);
    for (y = page_bottom; y > 0; y --)
      if (!cupsRasterWritePixels(outras, line, outheader.cupsBytesPerLine))
      {
	_cupsLangPrintFilter(stderr, "ERROR", _("Error sending raster data."));
	fprintf(stderr, "DEBUG: Unable to write line %d for page %d.\n",
	        page_bottom - y + page_top + inheader.cupsHeight + 1, page);
	return (1);
      }

    free(line);
  }

  cupsRasterClose(inras);
  if (fd)
    close(fd);

  cupsRasterClose(outras);

  return (0);
}
Example #16
0
static void
backend_init_supplies(
    int         snmp_fd,		/* I - SNMP socket */
    http_addr_t *addr)			/* I - Printer address */
{
  int		i,			/* Looping var */
		type;			/* Current marker type */
  cups_file_t	*cachefile;		/* Cache file */
  const char	*cachedir;		/* CUPS_CACHEDIR value */
  char		addrstr[1024],		/* Address string */
		cachefilename[1024],	/* Cache filename */
		description[CUPS_SNMP_MAX_STRING],
					/* Device description string */
		value[CUPS_MAX_SUPPLIES * (CUPS_SNMP_MAX_STRING * 4 + 3)],
					/* Value string */
		*ptr,			/* Pointer into value string */
		*name_ptr;		/* Pointer into name string */
  cups_snmp_t	packet;			/* SNMP response packet */
  ppd_file_t	*ppd;			/* PPD file for this queue */
  ppd_attr_t	*ppdattr;		/* cupsSNMPSupplies attribute */
  static const char * const types[] =	/* Supply types */
		{
		  "other",
		  "unknown",
		  "toner",
		  "waste-toner",
		  "ink",
		  "ink-cartridge",
		  "ink-ribbon",
		  "waste-ink",
		  "opc",
		  "developer",
		  "fuser-oil",
		  "solid-wax",
		  "ribbon-wax",
		  "waste-wax",
		  "fuser",
		  "corona-wire",
		  "fuser-oil-wick",
		  "cleaner-unit",
		  "fuser-cleaning-pad",
		  "transfer-unit",
		  "toner-cartridge",
		  "fuser-oiler",
		  "water",
		  "waste-water",
		  "glue-water-additive",
		  "waste-paper",
		  "binding-supply",
		  "banding-supply",
		  "stitching-wire",
		  "shrink-wrap",
		  "paper-wrap",
		  "staples",
		  "inserts",
		  "covers"
		};


 /*
  * Reset state information...
  */

  current_addr  = *addr;
  current_state = -1;
  num_supplies  = -1;
  charset       = -1;

  memset(supplies, 0, sizeof(supplies));

 /*
  * See if we should be getting supply levels via SNMP...
  */

  if ((ppd = ppdOpenFile(getenv("PPD"))) == NULL ||
      ((ppdattr = ppdFindAttr(ppd, "cupsSNMPSupplies", NULL)) != NULL &&
       ppdattr->value && _cups_strcasecmp(ppdattr->value, "true")))
  {
    ppdClose(ppd);
    return;
  }

  if ((ppdattr = ppdFindAttr(ppd, "cupsSNMPQuirks", NULL)) != NULL)
  {
    if (!_cups_strcasecmp(ppdattr->value, "capacity"))
      quirks |= CUPS_SNMP_CAPACITY;
  }

  ppdClose(ppd);

 /*
  * Get the device description...
  */

  if (!_cupsSNMPWrite(snmp_fd, addr, CUPS_SNMP_VERSION_1,
		     _cupsSNMPDefaultCommunity(), CUPS_ASN1_GET_REQUEST, 1,
		     hrDeviceDescr))
    return;

  if (!_cupsSNMPRead(snmp_fd, &packet, CUPS_SUPPLY_TIMEOUT) ||
      packet.object_type != CUPS_ASN1_OCTET_STRING)
  {
    strlcpy(description, "Unknown", sizeof(description));
    num_supplies = 0;
  }
  else
    strlcpy(description, (char *)packet.object_value.string.bytes,
            sizeof(description));

  fprintf(stderr, "DEBUG2: hrDeviceDesc=\"%s\"\n", description);

 /*
  * See if we have already queried this device...
  */

  httpAddrString(addr, addrstr, sizeof(addrstr));

  if ((cachedir = getenv("CUPS_CACHEDIR")) == NULL)
    cachedir = CUPS_CACHEDIR;

  snprintf(cachefilename, sizeof(cachefilename), "%s/%s.snmp", cachedir,
           addrstr);

  if ((cachefile = cupsFileOpen(cachefilename, "r")) != NULL)
  {
   /*
    * Yes, read the cache file:
    *
    *     3 num_supplies charset
    *     device description
    *     supply structures...
    */

    if (cupsFileGets(cachefile, value, sizeof(value)))
    {
      if (sscanf(value, "3 %d%d", &num_supplies, &charset) == 2 &&
          num_supplies <= CUPS_MAX_SUPPLIES &&
          cupsFileGets(cachefile, value, sizeof(value)))
      {
        if (!strcmp(description, value))
	  cupsFileRead(cachefile, (char *)supplies,
	               (size_t)num_supplies * sizeof(backend_supplies_t));
        else
	{
	  num_supplies = -1;
	  charset      = -1;
	}
      }
      else
      {
        num_supplies = -1;
	charset      = -1;
      }
    }

    cupsFileClose(cachefile);
  }

 /*
  * If the cache information isn't correct, scan for supplies...
  */

  if (charset < 0)
  {
   /*
    * Get the configured character set...
    */

    int	oid[CUPS_SNMP_MAX_OID];		/* OID for character set */


    if (!_cupsSNMPWrite(snmp_fd, &current_addr, CUPS_SNMP_VERSION_1,
			_cupsSNMPDefaultCommunity(), CUPS_ASN1_GET_REQUEST, 1,
			prtGeneralCurrentLocalization))
      return;

    if (!_cupsSNMPRead(snmp_fd, &packet, CUPS_SUPPLY_TIMEOUT) ||
	packet.object_type != CUPS_ASN1_INTEGER)
    {
      fprintf(stderr,
              "DEBUG: prtGeneralCurrentLocalization type is %x, expected %x!\n",
	      packet.object_type, CUPS_ASN1_INTEGER);
      return;
    }

    fprintf(stderr, "DEBUG2: prtGeneralCurrentLocalization=%d\n",
            packet.object_value.integer);

    _cupsSNMPCopyOID(oid, prtLocalizationCharacterSet, CUPS_SNMP_MAX_OID);
    oid[prtLocalizationCharacterSetOffset - 2] = packet.object_value.integer;


    if (!_cupsSNMPWrite(snmp_fd, &current_addr, CUPS_SNMP_VERSION_1,
			_cupsSNMPDefaultCommunity(), CUPS_ASN1_GET_REQUEST, 1,
			oid))
      return;

    if (!_cupsSNMPRead(snmp_fd, &packet, CUPS_SUPPLY_TIMEOUT) ||
	packet.object_type != CUPS_ASN1_INTEGER)
    {
      fprintf(stderr,
              "DEBUG: prtLocalizationCharacterSet type is %x, expected %x!\n",
	      packet.object_type, CUPS_ASN1_INTEGER);
      return;
    }

    fprintf(stderr, "DEBUG2: prtLocalizationCharacterSet=%d\n",
	    packet.object_value.integer);
    charset = packet.object_value.integer;
  }

  if (num_supplies < 0)
  {
   /*
    * Walk the printer configuration information...
    */

    _cupsSNMPWalk(snmp_fd, &current_addr, CUPS_SNMP_VERSION_1,
		  _cupsSNMPDefaultCommunity(), prtMarkerSuppliesEntry,
		  CUPS_SUPPLY_TIMEOUT, backend_walk_cb, NULL);
  }

 /*
  * Save the cached information...
  */

  if (num_supplies < 0)
    num_supplies = 0;

  if ((cachefile = cupsFileOpen(cachefilename, "w")) != NULL)
  {
    cupsFilePrintf(cachefile, "3 %d %d\n", num_supplies, charset);
    cupsFilePrintf(cachefile, "%s\n", description);

    if (num_supplies > 0)
      cupsFileWrite(cachefile, (char *)supplies,
                    (size_t)num_supplies * sizeof(backend_supplies_t));

    cupsFileClose(cachefile);
  }

  if (num_supplies <= 0)
    return;

 /*
  * Get the colors...
  */

  for (i = 0; i < num_supplies; i ++)
    strlcpy(supplies[i].color, "none", sizeof(supplies[i].color));

  _cupsSNMPWalk(snmp_fd, &current_addr, CUPS_SNMP_VERSION_1,
                _cupsSNMPDefaultCommunity(), prtMarkerColorantValue,
	        CUPS_SUPPLY_TIMEOUT, backend_walk_cb, NULL);

 /*
  * Output the marker-colors attribute...
  */

  for (i = 0, ptr = value; i < num_supplies; i ++, ptr += strlen(ptr))
  {
    if (i)
      *ptr++ = ',';

    strlcpy(ptr, supplies[i].color, sizeof(value) - (size_t)(ptr - value));
  }

  fprintf(stderr, "ATTR: marker-colors=%s\n", value);

 /*
  * Output the marker-names attribute (the double quoting is necessary to deal
  * with embedded quotes and commas in the marker names...)
  */

  for (i = 0, ptr = value; i < num_supplies; i ++)
  {
    if (i)
      *ptr++ = ',';

    *ptr++ = '\'';
    *ptr++ = '\"';
    for (name_ptr = supplies[i].name; *name_ptr;)
    {
      if (*name_ptr == '\\' || *name_ptr == '\"' || *name_ptr == '\'')
      {
        *ptr++ = '\\';
        *ptr++ = '\\';
        *ptr++ = '\\';
      }

      *ptr++ = *name_ptr++;
    }
    *ptr++ = '\"';
    *ptr++ = '\'';
  }

  *ptr = '\0';

  fprintf(stderr, "ATTR: marker-names=%s\n", value);

 /*
  * Output the marker-types attribute...
  */

  for (i = 0, ptr = value; i < num_supplies; i ++, ptr += strlen(ptr))
  {
    if (i)
      *ptr++ = ',';

    type = supplies[i].type;

    if (type < CUPS_TC_other || type > CUPS_TC_covers)
      strlcpy(ptr, "unknown", sizeof(value) - (size_t)(ptr - value));
    else
      strlcpy(ptr, types[type - CUPS_TC_other], sizeof(value) - (size_t)(ptr - value));
  }

  fprintf(stderr, "ATTR: marker-types=%s\n", value);
}
Example #17
0
static void
colord_register_printer(
    cupsd_printer_t *p)			/* I - printer */
{
  char		ppdfile[1024],		/* PPD filename */
		iccfile[1024];		/* ICC filename */
  ppd_file_t	*ppd;			/* PPD file */
  cups_array_t	*profiles;		/* Profile paths array */
  ppd_attr_t	*attr;			/* Profile attributes */
  const char	*device_colorspace;	/* Device colorspace */
  char		*format[3];		/* Qualifier format tuple */


 /*
  * Ensure we have a D-Bus connection...
  */

  if (!colord_con)
    return;

 /*
  * Try opening the PPD file for this printer...
  */

  snprintf(ppdfile, sizeof(ppdfile), "%s/ppd/%s.ppd", ServerRoot, p->name);
  if ((ppd = _ppdOpenFile(ppdfile, _PPD_LOCALIZATION_ICC_PROFILES)) == NULL)
    return;

 /*
  * Find out the qualifier format
  */

  colord_get_qualifier_format(ppd, format);

 /*
  * See if we have any embedded profiles...
  */

  profiles = cupsArrayNew3(NULL, NULL, NULL, 0, (cups_acopy_func_t)strdup,
			   (cups_afree_func_t)free);
  for (attr = ppdFindAttr(ppd, "cupsICCProfile", NULL);
       attr;
       attr = ppdFindNextAttr(ppd, "cupsICCProfile", NULL))
    if (attr->spec[0] && attr->value && attr->value[0])
    {
      if (attr->value[0] != '/')
        snprintf(iccfile, sizeof(iccfile), "%s/profiles/%s", DataDir,
                 attr->value);
      else
        strlcpy(iccfile, attr->value, sizeof(iccfile));

      if (_cupsFileCheck(iccfile, _CUPS_FILE_CHECK_FILE, !RunUser,
			 cupsdLogFCMessage, p))
	continue;

      colord_create_profile(profiles, p->name, attr->spec, COLORD_SPACE_UNKNOWN,
			    format, iccfile, COLORD_SCOPE_TEMP);
    }

 /*
  * Add the grayscale profile first.  We always have a grayscale profile.
  */

  colord_create_profile(profiles, p->name, "Gray..", COLORD_SPACE_GRAY,
                        format, NULL, COLORD_SCOPE_TEMP);

 /*
  * Then add the RGB/CMYK/DeviceN color profile...
  */

  device_colorspace = "unknown";
  switch (ppd->colorspace)
  {
    case PPD_CS_RGB :
    case PPD_CS_CMY :
        device_colorspace = COLORD_SPACE_RGB;
        colord_create_profile(profiles, p->name, "RGB..", COLORD_SPACE_RGB,
			      format, NULL, COLORD_SCOPE_TEMP);
        break;

    case PPD_CS_RGBK :
    case PPD_CS_CMYK :
        device_colorspace = COLORD_SPACE_CMYK;
        colord_create_profile(profiles, p->name, "CMYK..", COLORD_SPACE_CMYK,
                              format, NULL, COLORD_SCOPE_TEMP);
        break;

    case PPD_CS_GRAY :
        device_colorspace = COLORD_SPACE_GRAY;
        break;

    case PPD_CS_N :
        colord_create_profile(profiles, p->name, "DeviceN..",
                              COLORD_SPACE_UNKNOWN, format, NULL,
			      COLORD_SCOPE_TEMP);
        break;
  }

 /*
  * Register the device with colord.
  */

  cupsdLogMessage(CUPSD_LOG_INFO, "Registering ICC color profiles for \"%s\".",
                  p->name);
  colord_create_device(p, ppd, profiles, device_colorspace, format,
		       COLORD_RELATION_SOFT, COLORD_SCOPE_TEMP);

 /*
  * Free any memory we used...
  */

  cupsArrayDelete(profiles);

  free(format[0]);
  free(format[1]);
  free(format[2]);

  ppdClose(ppd);
}
Example #18
0
static void
apple_register_profiles(
    cupsd_printer_t *p)			/* I - Printer */
{
  int			i;		/* Looping var */
  char			ppdfile[1024],	/* PPD filename */
			iccfile[1024],	/* ICC filename */
			selector[PPD_MAX_NAME];
					/* Profile selection string */
  ppd_file_t		*ppd;		/* PPD file */
  ppd_attr_t		*attr,		/* Profile attributes */
			*profileid_attr,/* cupsProfileID attribute */
			*q1_attr,	/* ColorModel (or other) qualifier */
			*q2_attr,	/* MediaType (or other) qualifier */
			*q3_attr;	/* Resolution (or other) qualifier */
  char			q_keyword[PPD_MAX_NAME];
					/* Qualifier keyword */
  const char		*q1_choice,	/* ColorModel (or other) choice */
			*q2_choice,	/* MediaType (or other) choice */
			*q3_choice;	/* Resolution (or other) choice */
  ppd_option_t		*cm_option;	/* Color model option */
  ppd_choice_t		*cm_choice;	/* Color model choice */
  int			num_profiles;	/* Number of profiles */
  OSStatus		error = 0;	/* Last error */
  unsigned		device_id,	/* Printer device ID */
			profile_id = 0,	/* Profile ID */
			default_profile_id = 0;
					/* Default profile ID */
  CFMutableDictionaryRef device_name;	/* Printer device name dictionary */
  CFStringRef		printer_name;	/* Printer name string */
  cups_array_t		*languages;	/* Languages array */
  CFMutableDictionaryRef profiles,	/* Dictionary of profiles */
			profile;	/* Current profile info dictionary */
  CFStringRef		dict_key;	/* Key in factory profile dictionary */


 /*
  * Make sure ColorSync is available...
  */

  if (&ColorSyncRegisterDevice == NULL)
    return;

 /*
  * Try opening the PPD file for this printer...
  */

  snprintf(ppdfile, sizeof(ppdfile), "%s/ppd/%s.ppd", ServerRoot, p->name);
  if ((ppd = _ppdOpenFile(ppdfile, _PPD_LOCALIZATION_ICC_PROFILES)) == NULL)
    return;

 /*
  * See if we have any profiles...
  */

  for (num_profiles = 0, attr = ppdFindAttr(ppd, "cupsICCProfile", NULL);
       attr;
       attr = ppdFindNextAttr(ppd, "cupsICCProfile", NULL))
    if (attr->spec[0] && attr->value && attr->value[0])
    {
      if (attr->value[0] != '/')
	snprintf(iccfile, sizeof(iccfile), "%s/profiles/%s", DataDir,
		 attr->value);
      else
	strlcpy(iccfile, attr->value, sizeof(iccfile));

      if (access(iccfile, 0))
      {
        cupsdLogMessage(CUPSD_LOG_ERROR,
                        "%s: ICC Profile \"%s\" does not exist.", p->name,
                        iccfile);
        cupsdSetPrinterReasons(p, "+cups-missing-filter-warning");
	continue;
      }

      num_profiles ++;
    }

 /*
  * Create a dictionary for the factory profiles...
  */

  profiles = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
				       &kCFTypeDictionaryKeyCallBacks,
				       &kCFTypeDictionaryValueCallBacks);
  if (!profiles)
  {
    cupsdLogMessage(CUPSD_LOG_ERROR,
		    "Unable to allocate memory for factory profiles.");
    ppdClose(ppd);
    return;
  }

 /*
  * If we have profiles, add them...
  */

  if (num_profiles > 0)
  {
   /*
    * For CUPS PPDs, figure out the default profile selector values...
    */

    if ((attr = ppdFindAttr(ppd, "cupsICCQualifier1", NULL)) != NULL &&
	attr->value && attr->value[0])
    {
      snprintf(q_keyword, sizeof(q_keyword), "Default%s", attr->value);
      q1_attr = ppdFindAttr(ppd, q_keyword, NULL);
    }
    else if ((q1_attr = ppdFindAttr(ppd, "DefaultColorModel", NULL)) == NULL)
      q1_attr = ppdFindAttr(ppd, "DefaultColorSpace", NULL);

    if (q1_attr && q1_attr->value && q1_attr->value[0])
      q1_choice = q1_attr->value;
    else
      q1_choice = "";

    if ((attr = ppdFindAttr(ppd, "cupsICCQualifier2", NULL)) != NULL &&
	attr->value && attr->value[0])
    {
      snprintf(q_keyword, sizeof(q_keyword), "Default%s", attr->value);
      q2_attr = ppdFindAttr(ppd, q_keyword, NULL);
    }
    else
      q2_attr = ppdFindAttr(ppd, "DefaultMediaType", NULL);

    if (q2_attr && q2_attr->value && q2_attr->value[0])
      q2_choice = q2_attr->value;
    else
      q2_choice = NULL;

    if ((attr = ppdFindAttr(ppd, "cupsICCQualifier3", NULL)) != NULL &&
	attr->value && attr->value[0])
    {
      snprintf(q_keyword, sizeof(q_keyword), "Default%s", attr->value);
      q3_attr = ppdFindAttr(ppd, q_keyword, NULL);
    }
    else
      q3_attr = ppdFindAttr(ppd, "DefaultResolution", NULL);

    if (q3_attr && q3_attr->value && q3_attr->value[0])
      q3_choice = q3_attr->value;
    else
      q3_choice = NULL;

   /*
    * Loop through the profiles listed in the PPD...
    */

    languages = _ppdGetLanguages(ppd);

    for (attr = ppdFindAttr(ppd, "cupsICCProfile", NULL);
	 attr;
	 attr = ppdFindNextAttr(ppd, "cupsICCProfile", NULL))
      if (attr->spec[0] && attr->value && attr->value[0])
      {
       /*
        * Add this profile...
	*/

        if (attr->value[0] != '/')
	  snprintf(iccfile, sizeof(iccfile), "%s/profiles/%s", DataDir,
	           attr->value);
        else
	  strlcpy(iccfile, attr->value, sizeof(iccfile));

        if (_cupsFileCheck(iccfile, _CUPS_FILE_CHECK_FILE, !RunUser,
	                   cupsdLogFCMessage, p))
	  iccfile[0] = '\0';

	cupsArraySave(ppd->sorted_attrs);

	if ((profileid_attr = ppdFindAttr(ppd, "cupsProfileID",
					  attr->spec)) != NULL &&
	    profileid_attr->value && isdigit(profileid_attr->value[0] & 255))
	  profile_id = (unsigned)strtoul(profileid_attr->value, NULL, 10);
	else
	  profile_id = _ppdHashName(attr->spec);

	cupsArrayRestore(ppd->sorted_attrs);

	profile = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
					    &kCFTypeDictionaryKeyCallBacks,
					    &kCFTypeDictionaryValueCallBacks);
	if (!profile)
	{
	  cupsdLogMessage(CUPSD_LOG_ERROR,
	                  "Unable to allocate memory for color profile.");
	  CFRelease(profiles);
	  ppdClose(ppd);
	  return;
	}

	apple_init_profile(ppd, languages, profile, profile_id, attr->spec,
	                   attr->text[0] ? attr->text : attr->spec, iccfile);

	dict_key = CFStringCreateWithFormat(kCFAllocatorDefault, NULL,
	                                    CFSTR("%u"), profile_id);
	if (dict_key)
	{
	  CFDictionarySetValue(profiles, dict_key, profile);
	  CFRelease(dict_key);
	}

	CFRelease(profile);

       /*
        * See if this is the default profile...
	*/

        if (!default_profile_id && q1_choice && q2_choice && q3_choice)
	{
	  snprintf(selector, sizeof(selector), "%s.%s.%s", q1_choice, q2_choice,
	           q3_choice);
	  if (!strcmp(selector, attr->spec))
	    default_profile_id = profile_id;
	}

        if (!default_profile_id && q1_choice && q2_choice)
	{
	  snprintf(selector, sizeof(selector), "%s.%s.", q1_choice, q2_choice);
	  if (!strcmp(selector, attr->spec))
	    default_profile_id = profile_id;
	}

        if (!default_profile_id && q1_choice && q3_choice)
	{
	  snprintf(selector, sizeof(selector), "%s..%s", q1_choice, q3_choice);
	  if (!strcmp(selector, attr->spec))
	    default_profile_id = profile_id;
	}

        if (!default_profile_id && q1_choice)
	{
	  snprintf(selector, sizeof(selector), "%s..", q1_choice);
	  if (!strcmp(selector, attr->spec))
	    default_profile_id = profile_id;
	}

        if (!default_profile_id && q2_choice && q3_choice)
	{
	  snprintf(selector, sizeof(selector), ".%s.%s", q2_choice, q3_choice);
	  if (!strcmp(selector, attr->spec))
	    default_profile_id = profile_id;
	}

        if (!default_profile_id && q2_choice)
	{
	  snprintf(selector, sizeof(selector), ".%s.", q2_choice);
	  if (!strcmp(selector, attr->spec))
	    default_profile_id = profile_id;
	}

        if (!default_profile_id && q3_choice)
	{
	  snprintf(selector, sizeof(selector), "..%s", q3_choice);
	  if (!strcmp(selector, attr->spec))
	    default_profile_id = profile_id;
	}
      }

    _ppdFreeLanguages(languages);
  }
  else if ((cm_option = ppdFindOption(ppd, "ColorModel")) != NULL)
  {
   /*
    * Extract profiles from ColorModel option...
    */

    const char *profile_name;		/* Name of generic profile */


    num_profiles = cm_option->num_choices;

    for (i = cm_option->num_choices, cm_choice = cm_option->choices;
         i > 0;
	 i --, cm_choice ++)
    {
      if (!strcmp(cm_choice->choice, "Gray") ||
          !strcmp(cm_choice->choice, "Black"))
        profile_name = "Gray";
      else if (!strcmp(cm_choice->choice, "RGB") ||
               !strcmp(cm_choice->choice, "CMY"))
        profile_name = "RGB";
      else if (!strcmp(cm_choice->choice, "CMYK") ||
               !strcmp(cm_choice->choice, "KCMY"))
        profile_name = "CMYK";
      else
        profile_name = "DeviceN";

      snprintf(selector, sizeof(selector), "%s..", profile_name);
      profile_id = _ppdHashName(selector);

      profile = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
					  &kCFTypeDictionaryKeyCallBacks,
					  &kCFTypeDictionaryValueCallBacks);
      if (!profile)
      {
	cupsdLogMessage(CUPSD_LOG_ERROR,
			"Unable to allocate memory for color profile.");
	CFRelease(profiles);
	ppdClose(ppd);
	return;
      }

      apple_init_profile(ppd, NULL, profile, profile_id, cm_choice->choice,
                         cm_choice->text, NULL);

      dict_key = CFStringCreateWithFormat(kCFAllocatorDefault, NULL,
                                          CFSTR("%u"), profile_id);
      if (dict_key)
      {
	CFDictionarySetValue(profiles, dict_key, profile);
	CFRelease(dict_key);
      }

      CFRelease(profile);

      if (cm_choice->marked)
        default_profile_id = profile_id;
    }
  }
  else
  {
   /*
    * Use the default colorspace...
    */

    attr = ppdFindAttr(ppd, "DefaultColorSpace", NULL);

    num_profiles = (attr && ppd->colorspace == PPD_CS_GRAY) ? 1 : 2;

   /*
    * Add the grayscale profile first.  We always have a grayscale profile.
    */

    profile = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
				        &kCFTypeDictionaryKeyCallBacks,
				        &kCFTypeDictionaryValueCallBacks);

    if (!profile)
    {
      cupsdLogMessage(CUPSD_LOG_ERROR,
                      "Unable to allocate memory for color profile.");
      CFRelease(profiles);
      ppdClose(ppd);
      return;
    }

    profile_id = _ppdHashName("Gray..");
    apple_init_profile(ppd, NULL, profile, profile_id, "Gray", "Gray", NULL);

    dict_key = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%u"),
                                        profile_id);
    if (dict_key)
    {
      CFDictionarySetValue(profiles, dict_key, profile);
      CFRelease(dict_key);
    }

    CFRelease(profile);

   /*
    * Then add the RGB/CMYK/DeviceN color profile...
    */

    profile = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
				        &kCFTypeDictionaryKeyCallBacks,
				        &kCFTypeDictionaryValueCallBacks);

    if (!profile)
    {
      cupsdLogMessage(CUPSD_LOG_ERROR,
                      "Unable to allocate memory for color profile.");
      CFRelease(profiles);
      ppdClose(ppd);
      return;
    }

    switch (ppd->colorspace)
    {
      default :
      case PPD_CS_RGB :
      case PPD_CS_CMY :
          profile_id = _ppdHashName("RGB..");
          apple_init_profile(ppd, NULL, profile, profile_id, "RGB", "RGB",
	                     NULL);
          break;

      case PPD_CS_RGBK :
      case PPD_CS_CMYK :
          profile_id = _ppdHashName("CMYK..");
          apple_init_profile(ppd, NULL, profile, profile_id, "CMYK", "CMYK",
	                     NULL);
          break;

      case PPD_CS_GRAY :
          if (attr)
            break;

      case PPD_CS_N :
          profile_id = _ppdHashName("DeviceN..");
          apple_init_profile(ppd, NULL, profile, profile_id, "DeviceN",
	                     "DeviceN", NULL);
          break;
    }

    if (CFDictionaryGetCount(profile) > 0)
    {
      dict_key = CFStringCreateWithFormat(kCFAllocatorDefault, NULL,
                                          CFSTR("%u"), profile_id);
      if (dict_key)
      {
        CFDictionarySetValue(profiles, dict_key, profile);
        CFRelease(dict_key);
      }
    }

    CFRelease(profile);
  }

  if (num_profiles > 0)
  {
   /*
    * Make sure we have a default profile ID...
    */

    if (!default_profile_id)
      default_profile_id = profile_id;	/* Last profile */

    dict_key = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%u"),
                                        default_profile_id);
    if (dict_key)
    {
      CFDictionarySetValue(profiles, kColorSyncDeviceDefaultProfileID,
                           dict_key);
      CFRelease(dict_key);
    }

   /*
    * Get the device ID hash and pathelogical name dictionary.
    */

    cupsdLogMessage(CUPSD_LOG_INFO, "Registering ICC color profiles for \"%s\"",
		    p->name);

    device_id    = _ppdHashName(p->name);
    device_name  = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
					     &kCFTypeDictionaryKeyCallBacks,
					     &kCFTypeDictionaryValueCallBacks);
    printer_name = CFStringCreateWithCString(kCFAllocatorDefault,
                                             p->name, kCFStringEncodingUTF8);

    if (device_name && printer_name)
    {
     /*
      * Register the device with ColorSync...
      */

      CFTypeRef		deviceDictKeys[] =
      {					/* Device keys */
        kColorSyncDeviceDescriptions,
	kColorSyncFactoryProfiles,
	kColorSyncDeviceUserScope,
	kColorSyncDeviceHostScope
      };
      CFTypeRef 	deviceDictVals[] =
      {					/* Device values */
        device_name,
	profiles,
	kCFPreferencesAnyUser,
	kCFPreferencesCurrentHost
      };
      CFDictionaryRef	deviceDict;	/* Device dictionary */
      CFUUIDRef		deviceUUID;	/* Device UUID */

      CFDictionarySetValue(device_name, CFSTR("en_US"), printer_name);

      deviceDict = CFDictionaryCreate(kCFAllocatorDefault,
				      (const void **)deviceDictKeys,
				      (const void **)deviceDictVals,
				      sizeof(deviceDictKeys) /
				          sizeof(deviceDictKeys[0]),
				      &kCFTypeDictionaryKeyCallBacks,
				      &kCFTypeDictionaryValueCallBacks);
      deviceUUID = ColorSyncCreateUUIDFromUInt32(device_id);

      if (!deviceDict || !deviceUUID ||
	  !ColorSyncRegisterDevice(kColorSyncPrinterDeviceClass, deviceUUID,
				   deviceDict))
	error = 1001;

      if (deviceUUID)
        CFRelease(deviceUUID);

      if (deviceDict)
        CFRelease(deviceDict);
    }
    else
      error = 1000;

   /*
    * Clean up...
    */

    if (error != noErr)
      cupsdLogMessage(CUPSD_LOG_ERROR,
		      "Unable to register ICC color profiles for \"%s\": %d",
		      p->name, (int)error);

    if (printer_name)
      CFRelease(printer_name);

    if (device_name)
      CFRelease(device_name);
  }

 /*
  * Free any memory we used...
  */

  CFRelease(profiles);

  ppdClose(ppd);
}
Example #19
0
const char *				/* O - Value or NULL if not found */
ppdLocalizeIPPReason(
    ppd_file_t *ppd,			/* I - PPD file */
    const char *reason,			/* I - IPP reason keyword to look up */
    const char *scheme,			/* I - URI scheme or NULL for text */
    char       *buffer,			/* I - Value buffer */
    size_t     bufsize)			/* I - Size of value buffer */
{
  cups_lang_t	*lang;			/* Current language */
  ppd_attr_t	*locattr;		/* Localized attribute */
  char		ll_CC[6],		/* Language + country locale */
		*bufptr,		/* Pointer into buffer */
		*bufend,		/* Pointer to end of buffer */
		*valptr;		/* Pointer into value */
  int		ch;			/* Hex-encoded character */
  size_t	schemelen;		/* Length of scheme name */


 /*
  * Range check input...
  */

  if (buffer)
    *buffer = '\0';

  if (!ppd || !reason || (scheme && !*scheme) ||
      !buffer || bufsize < PPD_MAX_TEXT)
    return (NULL);

 /*
  * Get the default language...
  */

  lang = ppd_ll_CC(ll_CC, sizeof(ll_CC));

 /*
  * Find the localized attribute...
  */

  if ((locattr = _ppdLocalizedAttr(ppd, "cupsIPPReason", reason,
                                   ll_CC)) == NULL)
    locattr = ppdFindAttr(ppd, "cupsIPPReason", reason);

  if (!locattr)
  {
    if (lang && (!scheme || !strcmp(scheme, "text")))
    {
     /*
      * Try to localize a standard printer-state-reason keyword...
      */

      const char *message = NULL;	/* Localized message */

      if (!strncmp(reason, "media-needed", 12))
	message = _("Load paper.");
      else if (!strncmp(reason, "media-jam", 9))
	message = _("Paper jam.");
      else if (!strncmp(reason, "offline", 7) ||
		       !strncmp(reason, "shutdown", 8))
	message = _("The printer is not connected.");
      else if (!strncmp(reason, "toner-low", 9))
	message = _("The printer is low on toner.");
      else if (!strncmp(reason, "toner-empty", 11))
	message = _("The printer may be out of toner.");
      else if (!strncmp(reason, "cover-open", 10))
	message = _("The printer's cover is open.");
      else if (!strncmp(reason, "interlock-open", 14))
	message = _("The printer's interlock is open.");
      else if (!strncmp(reason, "door-open", 9))
	message = _("The printer's door is open.");
      else if (!strncmp(reason, "input-tray-missing", 18))
	message = _("Paper tray is missing.");
      else if (!strncmp(reason, "media-low", 9))
	message = _("Paper tray is almost empty.");
      else if (!strncmp(reason, "media-empty", 11))
	message = _("Paper tray is empty.");
      else if (!strncmp(reason, "output-tray-missing", 19))
	message = _("Output bin is missing.");
      else if (!strncmp(reason, "output-area-almost-full", 23))
	message = _("Output bin is almost full.");
      else if (!strncmp(reason, "output-area-full", 16))
	message = _("Output bin is full.");
      else if (!strncmp(reason, "marker-supply-low", 17))
	message = _("The printer is low on ink.");
      else if (!strncmp(reason, "marker-supply-empty", 19))
	message = _("The printer may be out of ink.");
      else if (!strncmp(reason, "marker-waste-almost-full", 24))
	message = _("The printer's waste bin is almost full.");
      else if (!strncmp(reason, "marker-waste-full", 17))
	message = _("The printer's waste bin is full.");
      else if (!strncmp(reason, "fuser-over-temp", 15))
	message = _("The fuser's temperature is high.");
      else if (!strncmp(reason, "fuser-under-temp", 16))
	message = _("The fuser's temperature is low.");
      else if (!strncmp(reason, "opc-near-eol", 12))
	message = _("The optical photoconductor will need to be replaced soon.");
      else if (!strncmp(reason, "opc-life-over", 13))
	message = _("The optical photoconductor needs to be replaced.");
      else if (!strncmp(reason, "developer-low", 13))
	message = _("The developer unit will need to be replaced soon.");
      else if (!strncmp(reason, "developer-empty", 15))
	message = _("The developer unit needs to be replaced.");

      if (message)
      {
        strlcpy(buffer, _cupsLangString(lang, message), bufsize);
	return (buffer);
      }
    }

    return (NULL);
  }

 /*
  * Now find the value we need...
  */

  bufend = buffer + bufsize - 1;

  if (!scheme || !strcmp(scheme, "text"))
  {
   /*
    * Copy a text value (either the translation text or text:... URIs from
    * the value...
    */

    strlcpy(buffer, locattr->text, bufsize);

    for (valptr = locattr->value, bufptr = buffer; *valptr && bufptr < bufend;)
    {
      if (!strncmp(valptr, "text:", 5))
      {
       /*
        * Decode text: URI and add to the buffer...
	*/

	valptr += 5;

        while (*valptr && !_cups_isspace(*valptr) && bufptr < bufend)
	{
	  if (*valptr == '%' && isxdigit(valptr[1] & 255) &&
	      isxdigit(valptr[2] & 255))
	  {
	   /*
	    * Pull a hex-encoded character from the URI...
	    */

            valptr ++;

	    if (isdigit(*valptr & 255))
	      ch = (*valptr - '0') << 4;
	    else
	      ch = (tolower(*valptr) - 'a' + 10) << 4;
	    valptr ++;

	    if (isdigit(*valptr & 255))
	      *bufptr++ = (char)(ch | (*valptr - '0'));
	    else
	      *bufptr++ = (char)(ch | (tolower(*valptr) - 'a' + 10));
	    valptr ++;
	  }
	  else if (*valptr == '+')
	  {
	    *bufptr++ = ' ';
	    valptr ++;
	  }
	  else
	    *bufptr++ = *valptr++;
        }
      }
      else
      {
       /*
        * Skip this URI...
	*/

        while (*valptr && !_cups_isspace(*valptr))
          valptr++;
      }

     /*
      * Skip whitespace...
      */

      while (_cups_isspace(*valptr))
	valptr ++;
    }

    if (bufptr > buffer)
      *bufptr = '\0';

    return (buffer);
  }
  else
  {
   /*
    * Copy a URI...
    */

    schemelen = strlen(scheme);
    if (scheme[schemelen - 1] == ':')	/* Force scheme to be just the name */
      schemelen --;

    for (valptr = locattr->value, bufptr = buffer; *valptr && bufptr < bufend;)
    {
      if ((!strncmp(valptr, scheme, schemelen) && valptr[schemelen] == ':') ||
          (*valptr == '/' && !strcmp(scheme, "file")))
      {
       /*
        * Copy URI...
	*/

        while (*valptr && !_cups_isspace(*valptr) && bufptr < bufend)
	  *bufptr++ = *valptr++;

	*bufptr = '\0';

	return (buffer);
      }
      else
      {
       /*
        * Skip this URI...
	*/

	while (*valptr && !_cups_isspace(*valptr))
	  valptr++;
      }

     /*
      * Skip whitespace...
      */

      while (_cups_isspace(*valptr))
	valptr ++;
    }

    return (NULL);
  }
}
Example #20
0
int					/* O - 0 on success, -1 on failure */
ppdEmitJCL(ppd_file_t *ppd,		/* I - PPD file record */
           FILE       *fp,		/* I - File to write to */
           int        job_id,		/* I - Job ID */
	   const char *user,		/* I - Username */
	   const char *title)		/* I - Title */
{
  char		*ptr;			/* Pointer into JCL string */
  char		temp[65],		/* Local title string */
		displaymsg[33];		/* Local display string */


 /*
  * Range check the input...
  */

  if (!ppd || !ppd->jcl_begin || !ppd->jcl_ps)
    return (0);

 /*
  * See if the printer supports HP PJL...
  */

  if (!strncmp(ppd->jcl_begin, "\033%-12345X@", 10))
  {
   /*
    * This printer uses HP PJL commands for output; filter the output
    * so that we only have a single "@PJL JOB" command in the header...
    *
    * To avoid bugs in the PJL implementation of certain vendors' products
    * (Xerox in particular), we add a dummy "@PJL" command at the beginning
    * of the PJL commands to initialize PJL processing.
    */

    ppd_attr_t	*charset;		/* PJL charset */
    ppd_attr_t	*display;		/* PJL display command */


    if ((charset = ppdFindAttr(ppd, "cupsPJLCharset", NULL)) != NULL)
    {
      if (!charset->value || _cups_strcasecmp(charset->value, "UTF-8"))
        charset = NULL;
    }

    if ((display = ppdFindAttr(ppd, "cupsPJLDisplay", NULL)) != NULL)
    {
      if (!display->value)
        display = NULL;
    }

    fputs("\033%-12345X@PJL\n", fp);
    for (ptr = ppd->jcl_begin + 9; *ptr;)
      if (!strncmp(ptr, "@PJL JOB", 8))
      {
       /*
        * Skip job command...
	*/

        for (;*ptr; ptr ++)
	  if (*ptr == '\n')
	    break;

	if (*ptr)
	  ptr ++;
      }
      else
      {
       /*
        * Copy line...
	*/

        for (;*ptr; ptr ++)
	{
	  putc(*ptr, fp);
	  if (*ptr == '\n')
	    break;
	}

	if (*ptr)
	  ptr ++;
      }

   /*
    * Clean up the job title...
    */

    if ((ptr = strrchr(title, '/')) != NULL)
    {
     /*
      * Only show basename of file path...
      */

      title = ptr + 1;
    }

    if (!strncmp(title, "smbprn.", 7))
    {
     /*
      * Skip leading smbprn.######## from Samba jobs...
      */

      for (title += 7; *title && isdigit(*title & 255); title ++);
      while (_cups_isspace(*title))
        title ++;

      if ((ptr = strstr(title, " - ")) != NULL)
      {
       /*
	* Skip application name in "Some Application - Title of job"...
	*/

	title = ptr + 3;
      }
    }

   /*
    * Replace double quotes with single quotes and UTF-8 characters with
    * question marks so that the title does not cause a PJL syntax error.
    */

    strlcpy(temp, title, sizeof(temp));

    for (ptr = temp; *ptr; ptr ++)
      if (*ptr == '\"')
        *ptr = '\'';
      else if (!charset && (*ptr & 128))
        *ptr = '?';

   /*
    * CUPS STR #3125: Long PJL JOB NAME causes problems with some printers
    *
    * Generate the display message, truncating at 32 characters + nul to avoid
    * issues with some printer's PJL implementations...
    */

    snprintf(displaymsg, sizeof(displaymsg), "%d %s %s", job_id, user, temp);

   /*
    * Send PJL JOB and PJL RDYMSG commands before we enter PostScript mode...
    */

    if (display && strcmp(display->value, "job"))
      fprintf(fp, "@PJL JOB NAME = \"%s\"\n", temp);
    else if (display && !strcmp(display->value, "rdymsg"))
      fprintf(fp, "@PJL RDYMSG DISPLAY = \"%s\"\n", displaymsg);
    else
      fprintf(fp, "@PJL JOB NAME = \"%s\" DISPLAY = \"%s\"\n", temp,
	      displaymsg);

   /*
    * Replace double quotes with single quotes and UTF-8 characters with
    * question marks so that the user does not cause a PJL syntax error.
    */

    strlcpy(temp, user, sizeof(temp));

    for (ptr = temp; *ptr; ptr ++)
      if (*ptr == '\"')
        *ptr = '\'';
      else if (!charset && (*ptr & 128))
        *ptr = '?';

    fprintf(fp, "@PJL SET USERNAME = \"%s\"\n", temp);
  }
  else
    fputs(ppd->jcl_begin, fp);

  ppdEmit(ppd, fp, PPD_ORDER_JCL);
  fputs(ppd->jcl_ps, fp);

  return (0);
}
Example #21
0
int					/* O - 0 on success, -1 on error */
ppdLocalize(ppd_file_t *ppd)		/* I - PPD file */
{
  int		i, j, k;		/* Looping vars */
  ppd_group_t	*group;			/* Current group */
  ppd_option_t	*option;		/* Current option */
  ppd_choice_t	*choice;		/* Current choice */
  ppd_coption_t	*coption;		/* Current custom option */
  ppd_cparam_t	*cparam;		/* Current custom parameter */
  ppd_attr_t	*attr,			/* Current attribute */
		*locattr;		/* Localized attribute */
  char		ckeyword[PPD_MAX_NAME],	/* Custom keyword */
		ll_CC[6];		/* Language + country locale */


 /*
  * Range check input...
  */

  DEBUG_printf(("ppdLocalize(ppd=%p)", ppd));

  if (!ppd)
    return (-1);

 /*
  * Get the default language...
  */

  ppd_ll_CC(ll_CC, sizeof(ll_CC));

 /*
  * Now lookup all of the groups, options, choices, etc.
  */

  for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++)
  {
    if ((locattr = _ppdLocalizedAttr(ppd, "Translation", group->name,
                                     ll_CC)) != NULL)
      strlcpy(group->text, locattr->text, sizeof(group->text));

    for (j = group->num_options, option = group->options; j > 0; j --, option ++)
    {
      if ((locattr = _ppdLocalizedAttr(ppd, "Translation", option->keyword,
                                       ll_CC)) != NULL)
	strlcpy(option->text, locattr->text, sizeof(option->text));

      for (k = option->num_choices, choice = option->choices;
           k > 0;
	   k --, choice ++)
      {
        if (strcmp(choice->choice, "Custom") ||
	    !ppdFindCustomOption(ppd, option->keyword))
	  locattr = _ppdLocalizedAttr(ppd, option->keyword, choice->choice,
	                              ll_CC);
	else
	{
	  snprintf(ckeyword, sizeof(ckeyword), "Custom%s", option->keyword);

	  locattr = _ppdLocalizedAttr(ppd, ckeyword, "True", ll_CC);
	}

        if (locattr)
	  strlcpy(choice->text, locattr->text, sizeof(choice->text));
      }
    }
  }

 /*
  * Translate any custom parameters...
  */

  for (coption = (ppd_coption_t *)cupsArrayFirst(ppd->coptions);
       coption;
       coption = (ppd_coption_t *)cupsArrayNext(ppd->coptions))
  {
    for (cparam = (ppd_cparam_t *)cupsArrayFirst(coption->params);
	 cparam;
	 cparam = (ppd_cparam_t *)cupsArrayNext(coption->params))
    {
      snprintf(ckeyword, sizeof(ckeyword), "ParamCustom%s", coption->keyword);

      if ((locattr = _ppdLocalizedAttr(ppd, ckeyword, cparam->name,
                                       ll_CC)) != NULL)
        strlcpy(cparam->text, locattr->text, sizeof(cparam->text));
    }
  }

 /*
  * Translate ICC profile names...
  */

  if ((attr = ppdFindAttr(ppd, "APCustomColorMatchingName", NULL)) != NULL)
  {
    if ((locattr = _ppdLocalizedAttr(ppd, "APCustomColorMatchingName",
                                     attr->spec, ll_CC)) != NULL)
      strlcpy(attr->text, locattr->text, sizeof(attr->text));
  }

  for (attr = ppdFindAttr(ppd, "cupsICCProfile", NULL);
       attr;
       attr = ppdFindNextAttr(ppd, "cupsICCProfile", NULL))
  {
    cupsArraySave(ppd->sorted_attrs);

    if ((locattr = _ppdLocalizedAttr(ppd, "cupsICCProfile", attr->spec,
                                     ll_CC)) != NULL)
      strlcpy(attr->text, locattr->text, sizeof(attr->text));

    cupsArrayRestore(ppd->sorted_attrs);
  }

 /*
  * Translate printer presets...
  */

  for (attr = ppdFindAttr(ppd, "APPrinterPreset", NULL);
       attr;
       attr = ppdFindNextAttr(ppd, "APPrinterPreset", NULL))
  {
    cupsArraySave(ppd->sorted_attrs);

    if ((locattr = _ppdLocalizedAttr(ppd, "APPrinterPreset", attr->spec,
                                     ll_CC)) != NULL)
      strlcpy(attr->text, locattr->text, sizeof(attr->text));

    cupsArrayRestore(ppd->sorted_attrs);
  }

  return (0);
}
Example #22
0
char *					/* O - String containing option code or @code NULL@ if there is no option code */
ppdEmitString(ppd_file_t    *ppd,	/* I - PPD file record */
              ppd_section_t section,	/* I - Section to write */
	      float         min_order)	/* I - Lowest OrderDependency */
{
  int		i, j,			/* Looping vars */
		count;			/* Number of choices */
  ppd_choice_t	**choices;		/* Choices */
  ppd_size_t	*size;			/* Custom page size */
  ppd_coption_t	*coption;		/* Custom option */
  ppd_cparam_t	*cparam;		/* Custom parameter */
  size_t	bufsize;		/* Size of string buffer needed */
  char		*buffer,		/* String buffer */
		*bufptr,		/* Pointer into buffer */
		*bufend;		/* End of buffer */
  struct lconv	*loc;			/* Locale data */


  DEBUG_printf(("ppdEmitString(ppd=%p, section=%d, min_order=%f)",
                ppd, section, min_order));

 /*
  * Range check input...
  */

  if (!ppd)
    return (NULL);

 /*
  * Use PageSize or PageRegion as required...
  */

  ppd_handle_media(ppd);

 /*
  * Collect the options we need to emit...
  */

  if ((count = ppdCollect2(ppd, section, min_order, &choices)) == 0)
    return (NULL);

 /*
  * Count the number of bytes that are required to hold all of the
  * option code...
  */

  for (i = 0, bufsize = 1; i < count; i ++)
  {
    if (section == PPD_ORDER_JCL)
    {
      if (!_cups_strcasecmp(choices[i]->choice, "Custom") &&
	  (coption = ppdFindCustomOption(ppd, choices[i]->option->keyword))
	      != NULL)
      {
       /*
        * Add space to account for custom parameter substitution...
	*/

        for (cparam = (ppd_cparam_t *)cupsArrayFirst(coption->params);
	     cparam;
	     cparam = (ppd_cparam_t *)cupsArrayNext(coption->params))
	{
          switch (cparam->type)
	  {
	    case PPD_CUSTOM_CURVE :
	    case PPD_CUSTOM_INVCURVE :
	    case PPD_CUSTOM_POINTS :
	    case PPD_CUSTOM_REAL :
	    case PPD_CUSTOM_INT :
	        bufsize += 10;
	        break;

	    case PPD_CUSTOM_PASSCODE :
	    case PPD_CUSTOM_PASSWORD :
	    case PPD_CUSTOM_STRING :
	        if (cparam->current.custom_string)
		  bufsize += strlen(cparam->current.custom_string);
	        break;
          }
	}
      }
    }
    else if (section != PPD_ORDER_EXIT)
    {
      bufsize += 3;			/* [{\n */

      if ((!_cups_strcasecmp(choices[i]->option->keyword, "PageSize") ||
           !_cups_strcasecmp(choices[i]->option->keyword, "PageRegion")) &&
          !_cups_strcasecmp(choices[i]->choice, "Custom"))
      {
        DEBUG_puts("2ppdEmitString: Custom size set!");

        bufsize += 37;			/* %%BeginFeature: *CustomPageSize True\n */
        bufsize += 50;			/* Five 9-digit numbers + newline */
      }
      else if (!_cups_strcasecmp(choices[i]->choice, "Custom") &&
               (coption = ppdFindCustomOption(ppd,
	                                      choices[i]->option->keyword))
	           != NULL)
      {
        bufsize += 23 + strlen(choices[i]->option->keyword) + 6;
					/* %%BeginFeature: *Customkeyword True\n */


        for (cparam = (ppd_cparam_t *)cupsArrayFirst(coption->params);
	     cparam;
	     cparam = (ppd_cparam_t *)cupsArrayNext(coption->params))
	{
          switch (cparam->type)
	  {
	    case PPD_CUSTOM_CURVE :
	    case PPD_CUSTOM_INVCURVE :
	    case PPD_CUSTOM_POINTS :
	    case PPD_CUSTOM_REAL :
	    case PPD_CUSTOM_INT :
	        bufsize += 10;
	        break;

	    case PPD_CUSTOM_PASSCODE :
	    case PPD_CUSTOM_PASSWORD :
	    case PPD_CUSTOM_STRING :
		bufsize += 3;
	        if (cparam->current.custom_string)
		  bufsize += 4 * strlen(cparam->current.custom_string);
	        break;
          }
	}
      }
      else
        bufsize += 17 + strlen(choices[i]->option->keyword) + 1 +
	           strlen(choices[i]->choice) + 1;
					/* %%BeginFeature: *keyword choice\n */

      bufsize += 13;			/* %%EndFeature\n */
      bufsize += 22;			/* } stopped cleartomark\n */
    }

    if (choices[i]->code)
      bufsize += strlen(choices[i]->code) + 1;
    else
      bufsize += strlen(ppd_custom_code);
  }

 /*
  * Allocate memory...
  */

  DEBUG_printf(("2ppdEmitString: Allocating %d bytes for string...",
                (int)bufsize));

  if ((buffer = calloc(1, bufsize)) == NULL)
  {
    free(choices);
    return (NULL);
  }

  bufend = buffer + bufsize - 1;
  loc    = localeconv();

 /*
  * Copy the option code to the buffer...
  */

  for (i = 0, bufptr = buffer; i < count; i ++, bufptr += strlen(bufptr))
    if (section == PPD_ORDER_JCL)
    {
      if (!_cups_strcasecmp(choices[i]->choice, "Custom") &&
	  choices[i]->code &&
          (coption = ppdFindCustomOption(ppd, choices[i]->option->keyword))
	      != NULL)
      {
       /*
        * Handle substitutions in custom JCL options...
	*/

	char	*cptr;			/* Pointer into code */
	int	pnum;			/* Parameter number */


        for (cptr = choices[i]->code; *cptr && bufptr < bufend;)
	{
	  if (*cptr == '\\')
	  {
	    cptr ++;

	    if (isdigit(*cptr & 255))
	    {
	     /*
	      * Substitute parameter...
	      */

              pnum = *cptr++ - '0';
	      while (isdigit(*cptr & 255))
	        pnum = pnum * 10 + *cptr++ - '0';

              for (cparam = (ppd_cparam_t *)cupsArrayFirst(coption->params);
	           cparam;
		   cparam = (ppd_cparam_t *)cupsArrayNext(coption->params))
		if (cparam->order == pnum)
		  break;

              if (cparam)
	      {
	        switch (cparam->type)
		{
		  case PPD_CUSTOM_CURVE :
		  case PPD_CUSTOM_INVCURVE :
		  case PPD_CUSTOM_POINTS :
		  case PPD_CUSTOM_REAL :
		      bufptr = _cupsStrFormatd(bufptr, bufend,
					       cparam->current.custom_real,
					       loc);
		      break;

		  case PPD_CUSTOM_INT :
		      snprintf(bufptr, bufend - bufptr, "%d",
		               cparam->current.custom_int);
		      bufptr += strlen(bufptr);
		      break;

		  case PPD_CUSTOM_PASSCODE :
		  case PPD_CUSTOM_PASSWORD :
		  case PPD_CUSTOM_STRING :
		      if (cparam->current.custom_string)
		      {
			strlcpy(bufptr, cparam->current.custom_string,
				bufend - bufptr);
			bufptr += strlen(bufptr);
		      }
		      break;
		}
	      }
	    }
	    else if (*cptr)
	      *bufptr++ = *cptr++;
	  }
	  else
	    *bufptr++ = *cptr++;
	}
      }
      else
      {
       /*
        * Otherwise just copy the option code directly...
	*/

        strlcpy(bufptr, choices[i]->code, bufend - bufptr + 1);
        bufptr += strlen(bufptr);
      }
    }
    else if (section != PPD_ORDER_EXIT)
    {
     /*
      * Add wrapper commands to prevent printer errors for unsupported
      * options...
      */

      strlcpy(bufptr, "[{\n", bufend - bufptr + 1);
      bufptr += 3;

     /*
      * Send DSC comments with option...
      */

      DEBUG_printf(("2ppdEmitString: Adding code for %s=%s...",
		    choices[i]->option->keyword, choices[i]->choice));

      if ((!_cups_strcasecmp(choices[i]->option->keyword, "PageSize") ||
           !_cups_strcasecmp(choices[i]->option->keyword, "PageRegion")) &&
          !_cups_strcasecmp(choices[i]->choice, "Custom"))
      {
       /*
        * Variable size; write out standard size options, using the
	* parameter positions defined in the PPD file...
	*/

        ppd_attr_t	*attr;		/* PPD attribute */
	int		pos,		/* Position of custom value */
			orientation;	/* Orientation to use */
	float		values[5];	/* Values for custom command */


        strlcpy(bufptr, "%%BeginFeature: *CustomPageSize True\n",
	        bufend - bufptr + 1);
        bufptr += 37;

        size = ppdPageSize(ppd, "Custom");

        memset(values, 0, sizeof(values));

	if ((attr = ppdFindAttr(ppd, "ParamCustomPageSize", "Width")) != NULL)
	{
	  pos = atoi(attr->value) - 1;

          if (pos < 0 || pos > 4)
	    pos = 0;
	}
	else
	  pos = 0;

	values[pos] = size->width;

	if ((attr = ppdFindAttr(ppd, "ParamCustomPageSize", "Height")) != NULL)
	{
	  pos = atoi(attr->value) - 1;

          if (pos < 0 || pos > 4)
	    pos = 1;
	}
	else
	  pos = 1;

	values[pos] = size->length;

       /*
        * According to the Adobe PPD specification, an orientation of 1
	* will produce a print that comes out upside-down with the X
	* axis perpendicular to the direction of feed, which is exactly
	* what we want to be consistent with non-PS printers.
	*
	* We could also use an orientation of 3 to produce output that
	* comes out rightside-up (this is the default for many large format
	* printer PPDs), however for consistency we will stick with the
	* value 1.
	*
	* If we wanted to get fancy, we could use orientations of 0 or
	* 2 and swap the width and length, however we don't want to get
	* fancy, we just want it to work consistently.
	*
	* The orientation value is range limited by the Orientation
	* parameter definition, so certain non-PS printer drivers that
	* only support an Orientation of 0 will get the value 0 as
	* expected.
	*/

        orientation = 1;

	if ((attr = ppdFindAttr(ppd, "ParamCustomPageSize",
	                        "Orientation")) != NULL)
	{
	  int min_orient, max_orient;	/* Minimum and maximum orientations */


          if (sscanf(attr->value, "%d%*s%d%d", &pos, &min_orient,
	             &max_orient) != 3)
	    pos = 4;
	  else
	  {
	    pos --;

            if (pos < 0 || pos > 4)
	      pos = 4;

            if (orientation > max_orient)
	      orientation = max_orient;
	    else if (orientation < min_orient)
	      orientation = min_orient;
	  }
	}
	else
	  pos = 4;

	values[pos] = (float)orientation;

        for (pos = 0; pos < 5; pos ++)
	{
	  bufptr    = _cupsStrFormatd(bufptr, bufend, values[pos], loc);
	  *bufptr++ = '\n';
        }

	if (!choices[i]->code)
	{
	 /*
	  * This can happen with certain buggy PPD files that don't include
	  * a CustomPageSize command sequence...  We just use a generic
	  * Level 2 command sequence...
	  */

	  strlcpy(bufptr, ppd_custom_code, bufend - bufptr + 1);
          bufptr += strlen(bufptr);
	}
      }
      else if (!_cups_strcasecmp(choices[i]->choice, "Custom") &&
               (coption = ppdFindCustomOption(ppd, choices[i]->option->keyword))
	           != NULL)
      {
       /*
        * Custom option...
	*/

        const char	*s;		/* Pointer into string value */
        cups_array_t	*params;	/* Parameters in the correct output order */


        params = cupsArrayNew((cups_array_func_t)ppd_compare_cparams, NULL);

        for (cparam = (ppd_cparam_t *)cupsArrayFirst(coption->params);
	     cparam;
	     cparam = (ppd_cparam_t *)cupsArrayNext(coption->params))
          cupsArrayAdd(params, cparam);

        snprintf(bufptr, bufend - bufptr + 1,
	         "%%%%BeginFeature: *Custom%s True\n", coption->keyword);
        bufptr += strlen(bufptr);

        for (cparam = (ppd_cparam_t *)cupsArrayFirst(params);
	     cparam;
	     cparam = (ppd_cparam_t *)cupsArrayNext(params))
	{
          switch (cparam->type)
	  {
	    case PPD_CUSTOM_CURVE :
	    case PPD_CUSTOM_INVCURVE :
	    case PPD_CUSTOM_POINTS :
	    case PPD_CUSTOM_REAL :
	        bufptr    = _cupsStrFormatd(bufptr, bufend,
		                            cparam->current.custom_real, loc);
                *bufptr++ = '\n';
	        break;

	    case PPD_CUSTOM_INT :
	        snprintf(bufptr, bufend - bufptr + 1, "%d\n",
		         cparam->current.custom_int);
		bufptr += strlen(bufptr);
	        break;

	    case PPD_CUSTOM_PASSCODE :
	    case PPD_CUSTOM_PASSWORD :
	    case PPD_CUSTOM_STRING :
	        *bufptr++ = '(';

		if (cparam->current.custom_string)
		{
		  for (s = cparam->current.custom_string; *s; s ++)
		  {
		    if (*s < ' ' || *s == '(' || *s == ')' || *s >= 127)
		    {
		      snprintf(bufptr, bufend - bufptr + 1, "\\%03o", *s & 255);
		      bufptr += strlen(bufptr);
		    }
		    else
		      *bufptr++ = *s;
		  }
		}

	        *bufptr++ = ')';
		*bufptr++ = '\n';
	        break;
          }
	}

	cupsArrayDelete(params);
      }
      else
      {
        snprintf(bufptr, bufend - bufptr + 1, "%%%%BeginFeature: *%s %s\n",
                 choices[i]->option->keyword, choices[i]->choice);
	bufptr += strlen(bufptr);
      }

      if (choices[i]->code && choices[i]->code[0])
      {
        j = (int)strlen(choices[i]->code);
	memcpy(bufptr, choices[i]->code, j);
	bufptr += j;

	if (choices[i]->code[j - 1] != '\n')
	  *bufptr++ = '\n';
      }

      strlcpy(bufptr, "%%EndFeature\n"
		      "} stopped cleartomark\n", bufend - bufptr + 1);
      bufptr += strlen(bufptr);

      DEBUG_printf(("2ppdEmitString: Offset in string is %d...",
                    (int)(bufptr - buffer)));
    }
    else
    {
      strlcpy(bufptr, choices[i]->code, bufend - bufptr + 1);
      bufptr += strlen(bufptr);
    }

 /*
  * Nul-terminate, free, and return...
  */

  *bufptr = '\0';

  free(choices);

  return (buffer);
}
Example #23
0
int					/* O - Number of options marked */
ppdCollect2(ppd_file_t    *ppd,		/* I - PPD file data */
            ppd_section_t section,	/* I - Section to collect */
	    float         min_order,	/* I - Minimum OrderDependency value */
            ppd_choice_t  ***choices)	/* O - Pointers to choices */
{
  ppd_choice_t	*c;			/* Current choice */
  ppd_section_t	csection;		/* Current section */
  float		corder;			/* Current OrderDependency value */
  int		count;			/* Number of choices collected */
  ppd_choice_t	**collect;		/* Collected choices */
  float		*orders;		/* Collected order values */


  DEBUG_printf(("ppdCollect2(ppd=%p, section=%d, min_order=%f, choices=%p)",
                ppd, section, min_order, choices));

  if (!ppd || !choices)
  {
    if (choices)
      *choices = NULL;

    return (0);
  }

 /*
  * Allocate memory for up to N selected choices...
  */

  count = 0;
  if ((collect = calloc(sizeof(ppd_choice_t *),
                        cupsArrayCount(ppd->marked))) == NULL)
  {
    *choices = NULL;
    return (0);
  }

  if ((orders = calloc(sizeof(float), cupsArrayCount(ppd->marked))) == NULL)
  {
    *choices = NULL;
    free(collect);
    return (0);
  }

 /*
  * Loop through all options and add choices as needed...
  */

  for (c = (ppd_choice_t *)cupsArrayFirst(ppd->marked);
       c;
       c = (ppd_choice_t *)cupsArrayNext(ppd->marked))
  {
    csection = c->option->section;
    corder   = c->option->order;

    if (!strcmp(c->choice, "Custom"))
    {
      ppd_attr_t	*attr;		/* NonUIOrderDependency value */
      float		aorder;		/* Order value */
      char		asection[17],	/* Section name */
			amain[PPD_MAX_NAME + 1],
			aoption[PPD_MAX_NAME];
					/* *CustomFoo and True */


      for (attr = ppdFindAttr(ppd, "NonUIOrderDependency", NULL);
           attr;
	   attr = ppdFindNextAttr(ppd, "NonUIOrderDependency", NULL))
        if (attr->value &&
	    sscanf(attr->value, "%f%16s%41s%40s", &aorder, asection, amain,
	           aoption) == 4 &&
	    !strncmp(amain, "*Custom", 7) &&
	    !strcmp(amain + 7, c->option->keyword) && !strcmp(aoption, "True"))
	{
	 /*
	  * Use this NonUIOrderDependency...
	  */

          corder = aorder;

	  if (!strcmp(asection, "DocumentSetup"))
	    csection = PPD_ORDER_DOCUMENT;
	  else if (!strcmp(asection, "ExitServer"))
	    csection = PPD_ORDER_EXIT;
	  else if (!strcmp(asection, "JCLSetup"))
	    csection = PPD_ORDER_JCL;
	  else if (!strcmp(asection, "PageSetup"))
	    csection = PPD_ORDER_PAGE;
	  else if (!strcmp(asection, "Prolog"))
	    csection = PPD_ORDER_PROLOG;
	  else
	    csection = PPD_ORDER_ANY;

	  break;
	}
    }

    if (csection == section && corder >= min_order)
    {
      collect[count] = c;
      orders[count]  = corder;
      count ++;
    }
  }

 /*
  * If we have more than 1 marked choice, sort them...
  */

  if (count > 1)
  {
    int i, j;				/* Looping vars */

    for (i = 0; i < (count - 1); i ++)
      for (j = i + 1; j < count; j ++)
        if (orders[i] > orders[j])
	{
	  c          = collect[i];
	  corder     = orders[i];
	  collect[i] = collect[j];
	  orders[i]  = orders[j];
	  collect[j] = c;
	  orders[j]  = corder;
	}
  }

  free(orders);

  DEBUG_printf(("2ppdCollect2: %d marked choices...", count));

 /*
  * Return the array and number of choices; if 0, free the array since
  * it isn't needed.
  */

  if (count > 0)
  {
    *choices = collect;
    return (count);
  }
  else
  {
    *choices = NULL;
    free(collect);
    return (0);
  }
}
Example #24
0
cups_array_t *				/* O - Languages array */
_ppdGetLanguages(ppd_file_t *ppd)	/* I - PPD file */
{
  cups_array_t	*languages;		/* Languages array */
  ppd_attr_t	*attr;			/* cupsLanguages attribute */
  char		*value,			/* Copy of attribute value */
		*start,			/* Start of current language */
		*ptr;			/* Pointer into languages */


 /*
  * See if we have a cupsLanguages attribute...
  */

  if ((attr = ppdFindAttr(ppd, "cupsLanguages", NULL)) == NULL || !attr->value)
    return (NULL);

 /*
  * Yes, load the list...
  */

  if ((languages = cupsArrayNew((cups_array_func_t)strcmp, NULL)) == NULL)
    return (NULL);

  if ((value = strdup(attr->value)) == NULL)
  {
    cupsArrayDelete(languages);
    return (NULL);
  }

  for (ptr = value; *ptr;)
  {
   /*
    * Skip leading whitespace...
    */

    while (_cups_isspace(*ptr))
      ptr ++;

    if (!*ptr)
      break;

   /*
    * Find the end of this language name...
    */

    for (start = ptr; *ptr && !_cups_isspace(*ptr); ptr ++);

    if (*ptr)
      *ptr++ = '\0';

    if (!strcmp(start, "en"))
      continue;

    cupsArrayAdd(languages, strdup(start));
  }

 /*
  * Free the temporary string and return either an array with one or more
  * values or a NULL pointer...
  */

  free(value);

  if (cupsArrayCount(languages) == 0)
  {
    cupsArrayDelete(languages);
    return (NULL);
  }
  else
    return (languages);
}
Example #25
0
int					/* O  - 1 on success, 0 on failure */
cupsResolveConflicts(
    ppd_file_t    *ppd,			/* I  - PPD file */
    const char    *option,		/* I  - Newly selected option or @code NULL@ for none */
    const char    *choice,		/* I  - Newly selected choice or @code NULL@ for none */
    int           *num_options,		/* IO - Number of additional selected options */
    cups_option_t **options)		/* IO - Additional selected options */
{
  int			i,		/* Looping var */
			tries,		/* Number of tries */
			num_newopts;	/* Number of new options */
  cups_option_t		*newopts;	/* New options */
  cups_array_t		*active = NULL,	/* Active constraints */
			*pass,		/* Resolvers for this pass */
			*resolvers,	/* Resolvers we have used */
			*test;		/* Test array for conflicts */
  _ppd_cups_uiconsts_t	*consts;	/* Current constraints */
  _ppd_cups_uiconst_t	*constptr;	/* Current constraint */
  ppd_attr_t		*resolver;	/* Current resolver */
  const char		*resval;	/* Pointer into resolver value */
  char			resoption[PPD_MAX_NAME],
					/* Current resolver option */
			reschoice[PPD_MAX_NAME],
					/* Current resolver choice */
			*resptr,	/* Pointer into option/choice */
			firstpage[255];	/* AP_FIRSTPAGE_Keyword string */
  const char		*value;		/* Selected option value */
  int			changed;	/* Did we change anything? */
  ppd_choice_t		*marked;	/* Marked choice */


 /*
  * Range check input...
  */

  if (!ppd || !num_options || !options || (option == NULL) != (choice == NULL))
    return (0);

 /*
  * Build a shadow option array...
  */

  num_newopts = 0;
  newopts     = NULL;

  for (i = 0; i < *num_options; i ++)
    num_newopts = cupsAddOption((*options)[i].name, (*options)[i].value,
                                num_newopts, &newopts);
  if (option && _cups_strcasecmp(option, "Collate"))
    num_newopts = cupsAddOption(option, choice, num_newopts, &newopts);

 /*
  * Loop until we have no conflicts...
  */

  cupsArraySave(ppd->sorted_attrs);

  resolvers = NULL;
  pass      = cupsArrayNew((cups_array_func_t)_cups_strcasecmp, NULL);
  tries     = 0;

  while (tries < 100 &&
         (active = ppd_test_constraints(ppd, NULL, NULL, num_newopts, newopts,
                                        _PPD_ALL_CONSTRAINTS)) != NULL)
  {
    tries ++;

    if (!resolvers)
      resolvers = cupsArrayNew((cups_array_func_t)_cups_strcasecmp, NULL);

    for (consts = (_ppd_cups_uiconsts_t *)cupsArrayFirst(active), changed = 0;
         consts;
	 consts = (_ppd_cups_uiconsts_t *)cupsArrayNext(active))
    {
      if (consts->resolver[0])
      {
       /*
        * Look up the resolver...
	*/

        if (cupsArrayFind(pass, consts->resolver))
	  continue;			/* Already applied this resolver... */

        if (cupsArrayFind(resolvers, consts->resolver))
	{
	 /*
	  * Resolver loop!
	  */

	  DEBUG_printf(("1cupsResolveConflicts: Resolver loop with %s!",
	                consts->resolver));
          goto error;
	}

        if ((resolver = ppdFindAttr(ppd, "cupsUIResolver",
	                            consts->resolver)) == NULL)
        {
	  DEBUG_printf(("1cupsResolveConflicts: Resolver %s not found!",
	                consts->resolver));
	  goto error;
	}

        if (!resolver->value)
	{
	  DEBUG_printf(("1cupsResolveConflicts: Resolver %s has no value!",
	                consts->resolver));
	  goto error;
	}

       /*
        * Add the options from the resolver...
	*/

        cupsArrayAdd(pass, consts->resolver);
	cupsArrayAdd(resolvers, consts->resolver);

        for (resval = resolver->value; *resval && !changed;)
	{
	  while (_cups_isspace(*resval))
	    resval ++;

	  if (*resval != '*')
	    break;

	  for (resval ++, resptr = resoption;
	       *resval && !_cups_isspace(*resval);
	       resval ++)
            if (resptr < (resoption + sizeof(resoption) - 1))
	      *resptr++ = *resval;

          *resptr = '\0';

	  while (_cups_isspace(*resval))
	    resval ++;

	  for (resptr = reschoice;
	       *resval && !_cups_isspace(*resval);
	       resval ++)
            if (resptr < (reschoice + sizeof(reschoice) - 1))
	      *resptr++ = *resval;

          *resptr = '\0';

          if (!resoption[0] || !reschoice[0])
	    break;

         /*
	  * Is this the option we are changing?
	  */

          snprintf(firstpage, sizeof(firstpage), "AP_FIRSTPAGE_%s", resoption);

	  if (option &&
	      (!_cups_strcasecmp(resoption, option) ||
	       !_cups_strcasecmp(firstpage, option) ||
	       (!_cups_strcasecmp(option, "PageSize") &&
		!_cups_strcasecmp(resoption, "PageRegion")) ||
	       (!_cups_strcasecmp(option, "AP_FIRSTPAGE_PageSize") &&
		!_cups_strcasecmp(resoption, "PageSize")) ||
	       (!_cups_strcasecmp(option, "AP_FIRSTPAGE_PageSize") &&
		!_cups_strcasecmp(resoption, "PageRegion")) ||
	       (!_cups_strcasecmp(option, "PageRegion") &&
	        !_cups_strcasecmp(resoption, "PageSize")) ||
	       (!_cups_strcasecmp(option, "AP_FIRSTPAGE_PageRegion") &&
	        !_cups_strcasecmp(resoption, "PageSize")) ||
	       (!_cups_strcasecmp(option, "AP_FIRSTPAGE_PageRegion") &&
	        !_cups_strcasecmp(resoption, "PageRegion"))))
	    continue;

	 /*
	  * Try this choice...
	  */

          if ((test = ppd_test_constraints(ppd, resoption, reschoice,
					   num_newopts, newopts,
					   _PPD_ALL_CONSTRAINTS)) == NULL)
	  {
	   /*
	    * That worked...
	    */

            changed = 1;
	  }
	  else
            cupsArrayDelete(test);

	 /*
	  * Add the option/choice from the resolver regardless of whether it
	  * worked; this makes sure that we can cascade several changes to
	  * make things resolve...
	  */

	  num_newopts = cupsAddOption(resoption, reschoice, num_newopts,
				      &newopts);
        }
      }
      else
      {
       /*
        * Try resolving by choosing the default values for non-installable
	* options, then by iterating through the possible choices...
	*/

        int		j;		/* Looping var */
	ppd_choice_t	*cptr;		/* Current choice */
        ppd_size_t	*size;		/* Current page size */


        for (i = consts->num_constraints, constptr = consts->constraints;
	     i > 0 && !changed;
	     i --, constptr ++)
	{
	 /*
	  * Can't resolve by changing an installable option...
	  */

	  if (constptr->installable)
	    continue;

         /*
	  * Is this the option we are changing?
	  */

	  if (option &&
	      (!_cups_strcasecmp(constptr->option->keyword, option) ||
	       (!_cups_strcasecmp(option, "PageSize") &&
		!_cups_strcasecmp(constptr->option->keyword, "PageRegion")) ||
	       (!_cups_strcasecmp(option, "PageRegion") &&
		!_cups_strcasecmp(constptr->option->keyword, "PageSize"))))
	    continue;

         /*
	  * Get the current option choice...
	  */

          if ((value = cupsGetOption(constptr->option->keyword, num_newopts,
	                             newopts)) == NULL)
          {
	    if (!_cups_strcasecmp(constptr->option->keyword, "PageSize") ||
	        !_cups_strcasecmp(constptr->option->keyword, "PageRegion"))
	    {
	      if ((value = cupsGetOption("PageSize", num_newopts,
	                                 newopts)) == NULL)
                value = cupsGetOption("PageRegion", num_newopts, newopts);

              if (!value)
	      {
	        if ((size = ppdPageSize(ppd, NULL)) != NULL)
		  value = size->name;
		else
		  value = "";
	      }
	    }
	    else
	    {
	      marked = ppdFindMarkedChoice(ppd, constptr->option->keyword);
	      value  = marked ? marked->choice : "";
	    }
	  }

	  if (!_cups_strncasecmp(value, "Custom.", 7))
	    value = "Custom";

         /*
	  * Try the default choice...
	  */

          test = NULL;

          if (_cups_strcasecmp(value, constptr->option->defchoice) &&
	      (test = ppd_test_constraints(ppd, constptr->option->keyword,
	                                   constptr->option->defchoice,
					   num_newopts, newopts,
					   _PPD_OPTION_CONSTRAINTS)) == NULL)
	  {
	   /*
	    * That worked...
	    */

	    num_newopts = cupsAddOption(constptr->option->keyword,
	                                constptr->option->defchoice,
					num_newopts, &newopts);
            changed     = 1;
	  }
	  else
	  {
	   /*
	    * Try each choice instead...
	    */

            for (j = constptr->option->num_choices,
	             cptr = constptr->option->choices;
		 j > 0;
		 j --, cptr ++)
            {
	      cupsArrayDelete(test);
	      test = NULL;

	      if (_cups_strcasecmp(value, cptr->choice) &&
	          _cups_strcasecmp(constptr->option->defchoice, cptr->choice) &&
		  _cups_strcasecmp("Custom", cptr->choice) &&
	          (test = ppd_test_constraints(ppd, constptr->option->keyword,
	                                       cptr->choice, num_newopts,
					       newopts,
					       _PPD_OPTION_CONSTRAINTS)) == NULL)
	      {
	       /*
		* This choice works...
		*/

		num_newopts = cupsAddOption(constptr->option->keyword,
					    cptr->choice, num_newopts,
					    &newopts);
		changed     = 1;
		break;
	      }
	    }

	    cupsArrayDelete(test);
          }
        }
      }
    }

    if (!changed)
    {
      DEBUG_puts("1cupsResolveConflicts: Unable to automatically resolve "
		 "constraint!");
      goto error;
    }

    cupsArrayClear(pass);
    cupsArrayDelete(active);
    active = NULL;
  }

  if (tries >= 100)
    goto error;

 /*
  * Free the caller's option array...
  */

  cupsFreeOptions(*num_options, *options);

 /*
  * If Collate is the option we are testing, add it here.  Otherwise, remove
  * any Collate option from the resolve list since the filters automatically
  * handle manual collation...
  */

  if (option && !_cups_strcasecmp(option, "Collate"))
    num_newopts = cupsAddOption(option, choice, num_newopts, &newopts);
  else
    num_newopts = cupsRemoveOption("Collate", num_newopts, &newopts);

 /*
  * Return the new list of options to the caller...
  */

  *num_options = num_newopts;
  *options     = newopts;

  cupsArrayDelete(pass);
  cupsArrayDelete(resolvers);

  cupsArrayRestore(ppd->sorted_attrs);

  DEBUG_printf(("1cupsResolveConflicts: Returning %d options:", num_newopts));
#ifdef DEBUG
  for (i = 0; i < num_newopts; i ++)
    DEBUG_printf(("1cupsResolveConflicts: options[%d]: %s=%s", i,
                  newopts[i].name, newopts[i].value));
#endif /* DEBUG */

  return (1);

 /*
  * If we get here, we failed to resolve...
  */

  error:

  cupsFreeOptions(num_newopts, newopts);

  cupsArrayDelete(active);
  cupsArrayDelete(pass);
  cupsArrayDelete(resolvers);

  cupsArrayRestore(ppd->sorted_attrs);

  DEBUG_puts("1cupsResolveConflicts: Unable to resolve conflicts!");

  return (0);
}
Example #26
0
void *					/* O - Data or NULL */
ppdxReadData(ppd_file_t *ppd,		/* I - PPD file */
             const char *name,		/* I - Keyword prefix */
             size_t     *datasize)	/* O - Size of data or NULL for don't care */
{
  char		keyword[PPD_MAX_NAME],	/* Keyword name */
		decoded[PPDX_MAX_CHUNK + 1];
					/* Decoded string */
  unsigned	chunk = 0;		/* Current chunk number */
  int		len;			/* Length of current chunk */
  ppd_attr_t	*attr;			/* Keyword/value from PPD file */
  Bytef		*data;			/* Pointer to data */
  size_t	alloc_size;		/* Allocated size of data buffer */
  z_stream	decomp;			/* Decompressor stream */
  int		error;			/* Error/status from inflate() */


 /*
  * Range check input...
  */

  if (datasize)
    *datasize = 0;

  if (!ppd || !name)
    return (NULL);

 /*
  * First see if there are any instances of the named keyword in the PPD...
  */

  snprintf(keyword, sizeof(keyword), "%s%04x", name, chunk);
  if ((attr = ppdFindAttr(ppd, keyword, NULL)) == NULL)
    return (NULL);

 /*
  * Allocate some memory and start decoding...
  */

  data       = malloc(257);
  alloc_size = 256;

  memset(&decomp, 0, sizeof(decomp));
  decomp.next_out  = data;
  decomp.avail_out = 256;

  inflateInit(&decomp);

  do
  {
   /*
    * Grab the data from the current attribute and decode it...
    */

    len = sizeof(decoded);
    if (!httpDecode64_2(decoded, &len, attr->value) || len == 0)
      break;

//    printf("chunk %04x has length %d\n", chunk, len);

   /*
    * Decompress this chunk...
    */

    decomp.next_in  = decoded;
    decomp.avail_in = len;

    do
    {
      Bytef	*temp;			/* Temporary pointer */
      size_t	temp_size;		/* Temporary allocation size */

//      printf("Before inflate: avail_in=%d, avail_out=%d\n", decomp.avail_in,
//             decomp.avail_out);

      if ((error = inflate(&decomp, Z_NO_FLUSH)) < Z_OK)
      {
        fprintf(stderr, "ERROR: inflate returned %d (%s)\n", error, decomp.msg);
        break;
      }

//      printf("After inflate: avail_in=%d, avail_out=%d, error=%d\n",
//             decomp.avail_in, decomp.avail_out, error);

      if (decomp.avail_out == 0)
      {
	if (alloc_size < 2048)
	  temp_size = alloc_size * 2;
	else if (alloc_size < PPDX_MAX_DATA)
	  temp_size = alloc_size + 2048;
	else
	  break;

	if ((temp = realloc(data, temp_size + 1)) == NULL)
	{
	  free(data);
	  return (NULL);
	}

	decomp.next_out  = temp + (decomp.next_out - data);
	decomp.avail_out = temp_size - alloc_size;
	data             = temp;
	alloc_size       = temp_size;
      }
    }
    while (decomp.avail_in > 0);

    chunk ++;
    snprintf(keyword, sizeof(keyword), "%s%04x", name, chunk);
  }
  while ((attr = ppdFindAttr(ppd, keyword, NULL)) != NULL);

  inflateEnd(&decomp);

 /*
  * Nul-terminate the data (usually a string)...
  */

  *(decomp.next_out) = '\0';

  if (datasize)
    *datasize = decomp.next_out - data;

  return (data);
}
Example #27
0
static void
ppd_load_constraints(ppd_file_t *ppd)	/* I - PPD file */
{
  int		i;			/* Looping var */
  ppd_const_t	*oldconst;		/* Current UIConstraints data */
  ppd_attr_t	*constattr;		/* Current cupsUIConstraints attribute */
  _ppd_cups_uiconsts_t	*consts;	/* Current cupsUIConstraints data */
  _ppd_cups_uiconst_t	*constptr;	/* Current constraint */
  ppd_group_t	*installable;		/* Installable options group */
  const char	*vptr;			/* Pointer into constraint value */
  char		option[PPD_MAX_NAME],	/* Option name/MainKeyword */
		choice[PPD_MAX_NAME],	/* Choice/OptionKeyword */
		*ptr;			/* Pointer into option or choice */


  DEBUG_printf(("7ppd_load_constraints(ppd=%p)", ppd));

 /*
  * Create an array to hold the constraint data...
  */

  ppd->cups_uiconstraints = cupsArrayNew(NULL, NULL);

 /*
  * Find the installable options group if it exists...
  */

  for (i = ppd->num_groups, installable = ppd->groups;
       i > 0;
       i --, installable ++)
    if (!_cups_strcasecmp(installable->name, "InstallableOptions"))
      break;

  if (i <= 0)
    installable = NULL;

 /*
  * Load old-style [Non]UIConstraints data...
  */

  for (i = ppd->num_consts, oldconst = ppd->consts; i > 0; i --, oldconst ++)
  {
   /*
    * Weed out nearby duplicates, since the PPD spec requires that you
    * define both "*Foo foo *Bar bar" and "*Bar bar *Foo foo"...
    */

    if (i > 1 &&
	!_cups_strcasecmp(oldconst[0].option1, oldconst[1].option2) &&
	!_cups_strcasecmp(oldconst[0].choice1, oldconst[1].choice2) &&
	!_cups_strcasecmp(oldconst[0].option2, oldconst[1].option1) &&
	!_cups_strcasecmp(oldconst[0].choice2, oldconst[1].choice1))
      continue;

   /*
    * Allocate memory...
    */

    if ((consts = calloc(1, sizeof(_ppd_cups_uiconsts_t))) == NULL)
    {
      DEBUG_puts("8ppd_load_constraints: Unable to allocate memory for "
		 "UIConstraints!");
      return;
    }

    if ((constptr = calloc(2, sizeof(_ppd_cups_uiconst_t))) == NULL)
    {
      free(consts);
      DEBUG_puts("8ppd_load_constraints: Unable to allocate memory for "
		 "UIConstraints!");
      return;
    }

   /*
    * Fill in the information...
    */

    consts->num_constraints = 2;
    consts->constraints     = constptr;

    if (!_cups_strncasecmp(oldconst->option1, "Custom", 6) &&
	!_cups_strcasecmp(oldconst->choice1, "True"))
    {
      constptr[0].option      = ppdFindOption(ppd, oldconst->option1 + 6);
      constptr[0].choice      = ppdFindChoice(constptr[0].option, "Custom");
      constptr[0].installable = 0;
    }
    else
    {
      constptr[0].option      = ppdFindOption(ppd, oldconst->option1);
      constptr[0].choice      = ppdFindChoice(constptr[0].option,
					      oldconst->choice1);
      constptr[0].installable = ppd_is_installable(installable,
						   oldconst->option1);
    }

    if (!constptr[0].option || (!constptr[0].choice && oldconst->choice1[0]))
    {
      DEBUG_printf(("8ppd_load_constraints: Unknown option *%s %s!",
		    oldconst->option1, oldconst->choice1));
      free(consts->constraints);
      free(consts);
      continue;
    }

    if (!_cups_strncasecmp(oldconst->option2, "Custom", 6) &&
	!_cups_strcasecmp(oldconst->choice2, "True"))
    {
      constptr[1].option      = ppdFindOption(ppd, oldconst->option2 + 6);
      constptr[1].choice      = ppdFindChoice(constptr[1].option, "Custom");
      constptr[1].installable = 0;
    }
    else
    {
      constptr[1].option      = ppdFindOption(ppd, oldconst->option2);
      constptr[1].choice      = ppdFindChoice(constptr[1].option,
					      oldconst->choice2);
      constptr[1].installable = ppd_is_installable(installable,
						   oldconst->option2);
    }

    if (!constptr[1].option || (!constptr[1].choice && oldconst->choice2[0]))
    {
      DEBUG_printf(("8ppd_load_constraints: Unknown option *%s %s!",
		    oldconst->option2, oldconst->choice2));
      free(consts->constraints);
      free(consts);
      continue;
    }

    consts->installable = constptr[0].installable || constptr[1].installable;

   /*
    * Add it to the constraints array...
    */

    cupsArrayAdd(ppd->cups_uiconstraints, consts);
  }

 /*
  * Then load new-style constraints...
  */

  for (constattr = ppdFindAttr(ppd, "cupsUIConstraints", NULL);
       constattr;
       constattr = ppdFindNextAttr(ppd, "cupsUIConstraints", NULL))
  {
    if (!constattr->value)
    {
      DEBUG_puts("8ppd_load_constraints: Bad cupsUIConstraints value!");
      continue;
    }

    for (i = 0, vptr = strchr(constattr->value, '*');
	 vptr;
	 i ++, vptr = strchr(vptr + 1, '*'));

    if (i == 0)
    {
      DEBUG_puts("8ppd_load_constraints: Bad cupsUIConstraints value!");
      continue;
    }

    if ((consts = calloc(1, sizeof(_ppd_cups_uiconsts_t))) == NULL)
    {
      DEBUG_puts("8ppd_load_constraints: Unable to allocate memory for "
		 "cupsUIConstraints!");
      return;
    }

    if ((constptr = calloc((size_t)i, sizeof(_ppd_cups_uiconst_t))) == NULL)
    {
      free(consts);
      DEBUG_puts("8ppd_load_constraints: Unable to allocate memory for "
		 "cupsUIConstraints!");
      return;
    }

    consts->num_constraints = i;
    consts->constraints     = constptr;

    strlcpy(consts->resolver, constattr->spec, sizeof(consts->resolver));

    for (i = 0, vptr = strchr(constattr->value, '*');
	 vptr;
	 i ++, vptr = strchr(vptr, '*'), constptr ++)
    {
     /*
      * Extract "*Option Choice" or just "*Option"...
      */

      for (vptr ++, ptr = option; *vptr && !_cups_isspace(*vptr); vptr ++)
	if (ptr < (option + sizeof(option) - 1))
	  *ptr++ = *vptr;

      *ptr = '\0';

      while (_cups_isspace(*vptr))
	vptr ++;

      if (*vptr == '*')
	choice[0] = '\0';
      else
      {
	for (ptr = choice; *vptr && !_cups_isspace(*vptr); vptr ++)
	  if (ptr < (choice + sizeof(choice) - 1))
	    *ptr++ = *vptr;

	*ptr = '\0';
      }

      if (!_cups_strncasecmp(option, "Custom", 6) && !_cups_strcasecmp(choice, "True"))
      {
	_cups_strcpy(option, option + 6);
	strlcpy(choice, "Custom", sizeof(choice));
      }

      constptr->option      = ppdFindOption(ppd, option);
      constptr->choice      = ppdFindChoice(constptr->option, choice);
      constptr->installable = ppd_is_installable(installable, option);
      consts->installable   |= constptr->installable;

      if (!constptr->option || (!constptr->choice && choice[0]))
      {
	DEBUG_printf(("8ppd_load_constraints: Unknown option *%s %s!",
		      option, choice));
	break;
      }
    }

    if (!vptr)
      cupsArrayAdd(ppd->cups_uiconstraints, consts);
    else
    {
      free(consts->constraints);
      free(consts);
    }
  }
}
Example #28
0
void dt_get_printer_info(const char *printer_name, dt_printer_info_t *pinfo)
{
  cups_dest_t *dests;
  int num_dests = cupsGetDests(&dests);
  cups_dest_t *dest = cupsGetDest(printer_name, NULL, num_dests, dests);

  if (dest)
  {
    const char *PPDFile = cupsGetPPD (printer_name);
    g_strlcpy(pinfo->name, dest->name, MAX_NAME);
    ppd_file_t *ppd = ppdOpenFile(PPDFile);

    if (ppd)
    {
      ppdMarkDefaults(ppd);
      cupsMarkOptions(ppd, dest->num_options, dest->options);

      // first check if this is turboprint drived printer, two solutions:
      // 1. ModelName constains TurboPrint
      // 2. zedoPrinterDriver exists
      ppd_attr_t *attr = ppdFindAttr(ppd, "ModelName", NULL);

      if (attr)
      {
        pinfo->is_turboprint = strstr(attr->value, "TurboPrint") != NULL;
      }

      // hardware margins

      attr = ppdFindAttr(ppd, "HWMargins", NULL);

      if (attr)
      {
        sscanf(attr->value, "%lf %lf %lf %lf",
               &pinfo->hw_margin_left, &pinfo->hw_margin_bottom,
               &pinfo->hw_margin_right, &pinfo->hw_margin_top);

        pinfo->hw_margin_left   = dt_pdf_point_to_mm (pinfo->hw_margin_left);
        pinfo->hw_margin_bottom = dt_pdf_point_to_mm (pinfo->hw_margin_bottom);
        pinfo->hw_margin_right  = dt_pdf_point_to_mm (pinfo->hw_margin_right);
        pinfo->hw_margin_top    = dt_pdf_point_to_mm (pinfo->hw_margin_top);
      }

      // default resolution

      attr = ppdFindAttr(ppd, "DefaultResolution", NULL);

      if (attr)
      {
        char *x = strstr(attr->value, "x");

        if (x)
          sscanf (x+1, "%ddpi", &pinfo->resolution);
        else
          sscanf (attr->value, "%ddpi", &pinfo->resolution);
      }
      else
        pinfo->resolution = 300;

      while(pinfo->resolution>360)
        pinfo->resolution /= 2.0;

      ppdClose(ppd);
      g_unlink(PPDFile);
    }
  }

  cupsFreeDests(num_dests, dests);
}
Example #29
0
int					/* O - Exit status */
main(int  argc,				/* I - Number of command-line arguments */
     char *argv[])			/* I - Command-line arguments */
{
  int		i;			/* Looping var */
  ppd_file_t	*ppd;			/* PPD file loaded from disk */
  int		status;			/* Status of tests (0 = success, 1 = fail) */
  int		conflicts;		/* Number of conflicts */
  char		*s;			/* String */
  char		buffer[8192];		/* String buffer */
  const char	*text,			/* Localized text */
		*val;			/* Option value */
  int		num_options;		/* Number of options */
  cups_option_t	*options;		/* Options */
  ppd_size_t	minsize,		/* Minimum size */
		maxsize,		/* Maximum size */
		*size;			/* Current size */
  ppd_attr_t	*attr;			/* Current attribute */
  _ppd_cache_t	*pc;			/* PPD cache */


  status = 0;

  if (argc == 1)
  {
   /*
    * Setup directories for locale stuff...
    */

    if (access("locale", 0))
    {
      mkdir("locale", 0777);
      mkdir("locale/fr", 0777);
      symlink("../../../locale/cups_fr.po", "locale/fr/cups_fr.po");
      mkdir("locale/zh_TW", 0777);
      symlink("../../../locale/cups_zh_TW.po", "locale/zh_TW/cups_zh_TW.po");
    }

    putenv("LOCALEDIR=locale");
    putenv("SOFTWARE=CUPS");

   /*
    * Do tests with test.ppd...
    */

    fputs("ppdOpenFile(test.ppd): ", stdout);

    if ((ppd = _ppdOpenFile("test.ppd", _PPD_LOCALIZATION_ALL)) != NULL)
      puts("PASS");
    else
    {
      ppd_status_t	err;		/* Last error in file */
      int		line;		/* Line number in file */


      status ++;
      err = ppdLastError(&line);

      printf("FAIL (%s on line %d)\n", ppdErrorString(err), line);
    }

    fputs("ppdFindAttr(wildcard): ", stdout);
    if ((attr = ppdFindAttr(ppd, "cupsTest", NULL)) == NULL)
    {
      status ++;
      puts("FAIL (not found)");
    }
    else if (strcmp(attr->name, "cupsTest") || strcmp(attr->spec, "Foo"))
    {
      status ++;
      printf("FAIL (got \"%s %s\")\n", attr->name, attr->spec);
    }
    else
      puts("PASS");

    fputs("ppdFindNextAttr(wildcard): ", stdout);
    if ((attr = ppdFindNextAttr(ppd, "cupsTest", NULL)) == NULL)
    {
      status ++;
      puts("FAIL (not found)");
    }
    else if (strcmp(attr->name, "cupsTest") || strcmp(attr->spec, "Bar"))
    {
      status ++;
      printf("FAIL (got \"%s %s\")\n", attr->name, attr->spec);
    }
    else
      puts("PASS");

    fputs("ppdFindAttr(Foo): ", stdout);
    if ((attr = ppdFindAttr(ppd, "cupsTest", "Foo")) == NULL)
    {
      status ++;
      puts("FAIL (not found)");
    }
    else if (strcmp(attr->name, "cupsTest") || strcmp(attr->spec, "Foo"))
    {
      status ++;
      printf("FAIL (got \"%s %s\")\n", attr->name, attr->spec);
    }
    else
      puts("PASS");

    fputs("ppdFindNextAttr(Foo): ", stdout);
    if ((attr = ppdFindNextAttr(ppd, "cupsTest", "Foo")) != NULL)
    {
      status ++;
      printf("FAIL (got \"%s %s\")\n", attr->name, attr->spec);
    }
    else
      puts("PASS");

    fputs("ppdMarkDefaults: ", stdout);
    ppdMarkDefaults(ppd);

    if ((conflicts = ppdConflicts(ppd)) == 0)
      puts("PASS");
    else
    {
      status ++;
      printf("FAIL (%d conflicts)\n", conflicts);
    }

    fputs("ppdEmitString (defaults): ", stdout);
    if ((s = ppdEmitString(ppd, PPD_ORDER_ANY, 0.0)) != NULL &&
	!strcmp(s, default_code))
      puts("PASS");
    else
    {
      status ++;
      printf("FAIL (%d bytes instead of %d)\n", s ? (int)strlen(s) : 0,
	     (int)strlen(default_code));

      if (s)
	puts(s);
    }

    if (s)
      free(s);

    fputs("ppdEmitString (custom size and string): ", stdout);
    ppdMarkOption(ppd, "PageSize", "Custom.400x500");
    ppdMarkOption(ppd, "StringOption", "{String1=\"value 1\" String2=value(2)}");

    if ((s = ppdEmitString(ppd, PPD_ORDER_ANY, 0.0)) != NULL &&
	!strcmp(s, custom_code))
      puts("PASS");
    else
    {
      status ++;
      printf("FAIL (%d bytes instead of %d)\n", s ? (int)strlen(s) : 0,
	     (int)strlen(custom_code));

      if (s)
	puts(s);
    }

    if (s)
      free(s);

   /*
    * Test constraints...
    */

    fputs("cupsGetConflicts(InputSlot=Envelope): ", stdout);
    ppdMarkOption(ppd, "PageSize", "Letter");

    num_options = cupsGetConflicts(ppd, "InputSlot", "Envelope", &options);
    if (num_options != 2 ||
        (val = cupsGetOption("PageRegion", num_options, options)) == NULL ||
	_cups_strcasecmp(val, "Letter") ||
	(val = cupsGetOption("PageSize", num_options, options)) == NULL ||
	_cups_strcasecmp(val, "Letter"))
    {
      printf("FAIL (%d options:", num_options);
      for (i = 0; i < num_options; i ++)
        printf(" %s=%s", options[i].name, options[i].value);
      puts(")");
      status ++;
    }
    else
      puts("PASS");

    fputs("ppdConflicts(): ", stdout);
    ppdMarkOption(ppd, "InputSlot", "Envelope");

    if ((conflicts = ppdConflicts(ppd)) == 2)
      puts("PASS (2)");
    else
    {
      printf("FAIL (%d)\n", conflicts);
      status ++;
    }

    fputs("cupsResolveConflicts(InputSlot=Envelope): ", stdout);
    num_options = 0;
    options     = NULL;
    if (!cupsResolveConflicts(ppd, "InputSlot", "Envelope", &num_options,
                             &options))
    {
      puts("FAIL (Unable to resolve)");
      status ++;
    }
    else if (num_options != 2 ||
             !cupsGetOption("PageSize", num_options, options))
    {
      printf("FAIL (%d options:", num_options);
      for (i = 0; i < num_options; i ++)
        printf(" %s=%s", options[i].name, options[i].value);
      puts(")");
      status ++;
    }
    else
      puts("PASS (Resolved by changing PageSize)");

    cupsFreeOptions(num_options, options);

    fputs("cupsResolveConflicts(No option/choice): ", stdout);
    num_options = 0;
    options     = NULL;
    if (cupsResolveConflicts(ppd, NULL, NULL, &num_options, &options) &&
        num_options == 1 && !_cups_strcasecmp(options[0].name, "InputSlot") &&
	!_cups_strcasecmp(options[0].value, "Tray"))
      puts("PASS (Resolved by changing InputSlot)");
    else if (num_options > 0)
    {
      printf("FAIL (%d options:", num_options);
      for (i = 0; i < num_options; i ++)
        printf(" %s=%s", options[i].name, options[i].value);
      puts(")");
      status ++;
    }
    else
    {
      puts("FAIL (Unable to resolve)");
      status ++;
    }
    cupsFreeOptions(num_options, options);

    fputs("ppdInstallableConflict(): ", stdout);
    if (ppdInstallableConflict(ppd, "Duplex", "DuplexNoTumble") &&
        !ppdInstallableConflict(ppd, "Duplex", "None"))
      puts("PASS");
    else if (!ppdInstallableConflict(ppd, "Duplex", "DuplexNoTumble"))
    {
      puts("FAIL (Duplex=DuplexNoTumble did not conflict)");
      status ++;
    }
    else
    {
      puts("FAIL (Duplex=None conflicted)");
      status ++;
    }

   /*
    * ppdPageSizeLimits
    */

    fputs("ppdPageSizeLimits: ", stdout);
    if (ppdPageSizeLimits(ppd, &minsize, &maxsize))
    {
      if (minsize.width != 36 || minsize.length != 36 ||
          maxsize.width != 1080 || maxsize.length != 86400)
      {
        printf("FAIL (got min=%.0fx%.0f, max=%.0fx%.0f, "
	       "expected min=36x36, max=1080x86400)\n", minsize.width,
	       minsize.length, maxsize.width, maxsize.length);
        status ++;
      }
      else
        puts("PASS");
    }
    else
    {
      puts("FAIL (returned 0)");
      status ++;
    }

   /*
    * cupsMarkOptions with PWG and IPP size names.
    */

    fputs("cupsMarkOptions(media=iso-a4): ", stdout);
    num_options = cupsAddOption("media", "iso-a4", 0, &options);
    cupsMarkOptions(ppd, num_options, options);
    cupsFreeOptions(num_options, options);

    size = ppdPageSize(ppd, NULL);
    if (!size || strcmp(size->name, "A4"))
    {
      printf("FAIL (%s)\n", size ? size->name : "unknown");
      status ++;
    }
    else
      puts("PASS");

    fputs("cupsMarkOptions(media=na_letter_8.5x11in): ", stdout);
    num_options = cupsAddOption("media", "na_letter_8.5x11in", 0, &options);
    cupsMarkOptions(ppd, num_options, options);
    cupsFreeOptions(num_options, options);

    size = ppdPageSize(ppd, NULL);
    if (!size || strcmp(size->name, "Letter"))
    {
      printf("FAIL (%s)\n", size ? size->name : "unknown");
      status ++;
    }
    else
      puts("PASS");

    fputs("cupsMarkOptions(media=oe_letter-fullbleed_8.5x11in): ", stdout);
    num_options = cupsAddOption("media", "oe_letter-fullbleed_8.5x11in", 0,
                                &options);
    cupsMarkOptions(ppd, num_options, options);
    cupsFreeOptions(num_options, options);

    size = ppdPageSize(ppd, NULL);
    if (!size || strcmp(size->name, "Letter.Fullbleed"))
    {
      printf("FAIL (%s)\n", size ? size->name : "unknown");
      status ++;
    }
    else
      puts("PASS");

    fputs("cupsMarkOptions(media=A4): ", stdout);
    num_options = cupsAddOption("media", "A4", 0, &options);
    cupsMarkOptions(ppd, num_options, options);
    cupsFreeOptions(num_options, options);

    size = ppdPageSize(ppd, NULL);
    if (!size || strcmp(size->name, "A4"))
    {
      printf("FAIL (%s)\n", size ? size->name : "unknown");
      status ++;
    }
    else
      puts("PASS");

   /*
    * Custom sizes...
    */

    fputs("cupsMarkOptions(media=Custom.8x10in): ", stdout);
    num_options = cupsAddOption("media", "Custom.8x10in", 0, &options);
    cupsMarkOptions(ppd, num_options, options);
    cupsFreeOptions(num_options, options);

    size = ppdPageSize(ppd, NULL);
    if (!size || strcmp(size->name, "Custom") ||
        size->width != 576 || size->length != 720)
    {
      printf("FAIL (%s - %gx%g)\n", size ? size->name : "unknown",
             size ? size->width : 0.0, size ? size->length : 0.0);
      status ++;
    }
    else
      puts("PASS");

   /*
    * Test localization...
    */

    fputs("ppdLocalizeIPPReason(text): ", stdout);
    if (ppdLocalizeIPPReason(ppd, "foo", NULL, buffer, sizeof(buffer)) &&
        !strcmp(buffer, "Foo Reason"))
      puts("PASS");
    else
    {
      status ++;
      printf("FAIL (\"%s\" instead of \"Foo Reason\")\n", buffer);
    }

    fputs("ppdLocalizeIPPReason(http): ", stdout);
    if (ppdLocalizeIPPReason(ppd, "foo", "http", buffer, sizeof(buffer)) &&
        !strcmp(buffer, "http://foo/bar.html"))
      puts("PASS");
    else
    {
      status ++;
      printf("FAIL (\"%s\" instead of \"http://foo/bar.html\")\n", buffer);
    }

    fputs("ppdLocalizeIPPReason(help): ", stdout);
    if (ppdLocalizeIPPReason(ppd, "foo", "help", buffer, sizeof(buffer)) &&
        !strcmp(buffer, "help:anchor='foo'%20bookID=Vendor%20Help"))
      puts("PASS");
    else
    {
      status ++;
      printf("FAIL (\"%s\" instead of \"help:anchor='foo'%%20bookID=Vendor%%20Help\")\n", buffer);
    }

    fputs("ppdLocalizeIPPReason(file): ", stdout);
    if (ppdLocalizeIPPReason(ppd, "foo", "file", buffer, sizeof(buffer)) &&
        !strcmp(buffer, "/help/foo/bar.html"))
      puts("PASS");
    else
    {
      status ++;
      printf("FAIL (\"%s\" instead of \"/help/foo/bar.html\")\n", buffer);
    }

    putenv("LANG=fr");
    putenv("LC_ALL=fr");
    putenv("LC_CTYPE=fr");
    putenv("LC_MESSAGES=fr");

    fputs("ppdLocalizeIPPReason(fr text): ", stdout);
    if (ppdLocalizeIPPReason(ppd, "foo", NULL, buffer, sizeof(buffer)) &&
        !strcmp(buffer, "La Long Foo Reason"))
      puts("PASS");
    else
    {
      status ++;
      printf("FAIL (\"%s\" instead of \"La Long Foo Reason\")\n", buffer);
    }

    putenv("LANG=zh_TW");
    putenv("LC_ALL=zh_TW");
    putenv("LC_CTYPE=zh_TW");
    putenv("LC_MESSAGES=zh_TW");

    fputs("ppdLocalizeIPPReason(zh_TW text): ", stdout);
    if (ppdLocalizeIPPReason(ppd, "foo", NULL, buffer, sizeof(buffer)) &&
        !strcmp(buffer, "Number 1 Foo Reason"))
      puts("PASS");
    else
    {
      status ++;
      printf("FAIL (\"%s\" instead of \"Number 1 Foo Reason\")\n", buffer);
    }

   /*
    * cupsMarkerName localization...
    */

    putenv("LANG=en");
    putenv("LC_ALL=en");
    putenv("LC_CTYPE=en");
    putenv("LC_MESSAGES=en");

    fputs("ppdLocalizeMarkerName(bogus): ", stdout);

    if ((text = ppdLocalizeMarkerName(ppd, "bogus")) != NULL)
    {
      status ++;
      printf("FAIL (\"%s\" instead of NULL)\n", text);
    }
    else
      puts("PASS");

    fputs("ppdLocalizeMarkerName(cyan): ", stdout);

    if ((text = ppdLocalizeMarkerName(ppd, "cyan")) != NULL &&
        !strcmp(text, "Cyan Toner"))
      puts("PASS");
    else
    {
      status ++;
      printf("FAIL (\"%s\" instead of \"Cyan Toner\")\n",
             text ? text : "(null)");
    }

    putenv("LANG=fr");
    putenv("LC_ALL=fr");
    putenv("LC_CTYPE=fr");
    putenv("LC_MESSAGES=fr");

    fputs("ppdLocalizeMarkerName(fr cyan): ", stdout);
    if ((text = ppdLocalizeMarkerName(ppd, "cyan")) != NULL &&
        !strcmp(text, "La Toner Cyan"))
      puts("PASS");
    else
    {
      status ++;
      printf("FAIL (\"%s\" instead of \"La Toner Cyan\")\n",
             text ? text : "(null)");
    }

    putenv("LANG=zh_TW");
    putenv("LC_ALL=zh_TW");
    putenv("LC_CTYPE=zh_TW");
    putenv("LC_MESSAGES=zh_TW");

    fputs("ppdLocalizeMarkerName(zh_TW cyan): ", stdout);
    if ((text = ppdLocalizeMarkerName(ppd, "cyan")) != NULL &&
        !strcmp(text, "Number 1 Cyan Toner"))
      puts("PASS");
    else
    {
      status ++;
      printf("FAIL (\"%s\" instead of \"Number 1 Cyan Toner\")\n",
             text ? text : "(null)");
    }

    ppdClose(ppd);

   /*
    * Test new constraints...
    */

    fputs("ppdOpenFile(test2.ppd): ", stdout);

    if ((ppd = ppdOpenFile("test2.ppd")) != NULL)
      puts("PASS");
    else
    {
      ppd_status_t	err;		/* Last error in file */
      int		line;		/* Line number in file */


      status ++;
      err = ppdLastError(&line);

      printf("FAIL (%s on line %d)\n", ppdErrorString(err), line);
    }

    fputs("ppdMarkDefaults: ", stdout);
    ppdMarkDefaults(ppd);

    if ((conflicts = ppdConflicts(ppd)) == 0)
      puts("PASS");
    else
    {
      status ++;
      printf("FAIL (%d conflicts)\n", conflicts);
    }

    fputs("ppdEmitString (defaults): ", stdout);
    if ((s = ppdEmitString(ppd, PPD_ORDER_ANY, 0.0)) != NULL &&
	!strcmp(s, default2_code))
      puts("PASS");
    else
    {
      status ++;
      printf("FAIL (%d bytes instead of %d)\n", s ? (int)strlen(s) : 0,
	     (int)strlen(default2_code));

      if (s)
	puts(s);
    }

    if (s)
      free(s);

    fputs("ppdConflicts(): ", stdout);
    ppdMarkOption(ppd, "PageSize", "Env10");
    ppdMarkOption(ppd, "InputSlot", "Envelope");
    ppdMarkOption(ppd, "Quality", "Photo");

    if ((conflicts = ppdConflicts(ppd)) == 1)
      puts("PASS (1)");
    else
    {
      printf("FAIL (%d)\n", conflicts);
      status ++;
    }

    fputs("cupsResolveConflicts(Quality=Photo): ", stdout);
    num_options = 0;
    options     = NULL;
    if (cupsResolveConflicts(ppd, "Quality", "Photo", &num_options,
                             &options))
    {
      printf("FAIL (%d options:", num_options);
      for (i = 0; i < num_options; i ++)
        printf(" %s=%s", options[i].name, options[i].value);
      puts(")");
      status ++;
    }
    else
      puts("PASS (Unable to resolve)");
    cupsFreeOptions(num_options, options);

    fputs("cupsResolveConflicts(No option/choice): ", stdout);
    num_options = 0;
    options     = NULL;
    if (cupsResolveConflicts(ppd, NULL, NULL, &num_options, &options) &&
        num_options == 1 && !_cups_strcasecmp(options->name, "Quality") &&
	!_cups_strcasecmp(options->value, "Normal"))
      puts("PASS");
    else if (num_options > 0)
    {
      printf("FAIL (%d options:", num_options);
      for (i = 0; i < num_options; i ++)
        printf(" %s=%s", options[i].name, options[i].value);
      puts(")");
      status ++;
    }
    else
    {
      puts("FAIL (Unable to resolve!)");
      status ++;
    }
    cupsFreeOptions(num_options, options);

    fputs("cupsResolveConflicts(loop test): ", stdout);
    ppdMarkOption(ppd, "PageSize", "A4");
    ppdMarkOption(ppd, "InputSlot", "Tray");
    ppdMarkOption(ppd, "Quality", "Photo");
    num_options = 0;
    options     = NULL;
    if (!cupsResolveConflicts(ppd, NULL, NULL, &num_options, &options))
      puts("PASS");
    else if (num_options > 0)
    {
      printf("FAIL (%d options:", num_options);
      for (i = 0; i < num_options; i ++)
        printf(" %s=%s", options[i].name, options[i].value);
      puts(")");
    }
    else
      puts("FAIL (No conflicts!)");

    fputs("ppdInstallableConflict(): ", stdout);
    if (ppdInstallableConflict(ppd, "Duplex", "DuplexNoTumble") &&
        !ppdInstallableConflict(ppd, "Duplex", "None"))
      puts("PASS");
    else if (!ppdInstallableConflict(ppd, "Duplex", "DuplexNoTumble"))
    {
      puts("FAIL (Duplex=DuplexNoTumble did not conflict)");
      status ++;
    }
    else
    {
      puts("FAIL (Duplex=None conflicted)");
      status ++;
    }

   /*
    * ppdPageSizeLimits
    */

    ppdMarkDefaults(ppd);

    fputs("ppdPageSizeLimits(default): ", stdout);
    if (ppdPageSizeLimits(ppd, &minsize, &maxsize))
    {
      if (minsize.width != 36 || minsize.length != 36 ||
          maxsize.width != 1080 || maxsize.length != 86400)
      {
        printf("FAIL (got min=%.0fx%.0f, max=%.0fx%.0f, "
	       "expected min=36x36, max=1080x86400)\n", minsize.width,
	       minsize.length, maxsize.width, maxsize.length);
        status ++;
      }
      else
        puts("PASS");
    }
    else
    {
      puts("FAIL (returned 0)");
      status ++;
    }

    ppdMarkOption(ppd, "InputSlot", "Manual");

    fputs("ppdPageSizeLimits(InputSlot=Manual): ", stdout);
    if (ppdPageSizeLimits(ppd, &minsize, &maxsize))
    {
      if (minsize.width != 100 || minsize.length != 100 ||
          maxsize.width != 1000 || maxsize.length != 1000)
      {
        printf("FAIL (got min=%.0fx%.0f, max=%.0fx%.0f, "
	       "expected min=100x100, max=1000x1000)\n", minsize.width,
	       minsize.length, maxsize.width, maxsize.length);
        status ++;
      }
      else
        puts("PASS");
    }
    else
    {
      puts("FAIL (returned 0)");
      status ++;
    }

    ppdMarkOption(ppd, "Quality", "Photo");

    fputs("ppdPageSizeLimits(Quality=Photo): ", stdout);
    if (ppdPageSizeLimits(ppd, &minsize, &maxsize))
    {
      if (minsize.width != 200 || minsize.length != 200 ||
          maxsize.width != 1000 || maxsize.length != 1000)
      {
        printf("FAIL (got min=%.0fx%.0f, max=%.0fx%.0f, "
	       "expected min=200x200, max=1000x1000)\n", minsize.width,
	       minsize.length, maxsize.width, maxsize.length);
        status ++;
      }
      else
        puts("PASS");
    }
    else
    {
      puts("FAIL (returned 0)");
      status ++;
    }

    ppdMarkOption(ppd, "InputSlot", "Tray");

    fputs("ppdPageSizeLimits(Quality=Photo): ", stdout);
    if (ppdPageSizeLimits(ppd, &minsize, &maxsize))
    {
      if (minsize.width != 300 || minsize.length != 300 ||
          maxsize.width != 1080 || maxsize.length != 86400)
      {
        printf("FAIL (got min=%.0fx%.0f, max=%.0fx%.0f, "
	       "expected min=300x300, max=1080x86400)\n", minsize.width,
	       minsize.length, maxsize.width, maxsize.length);
        status ++;
      }
      else
        puts("PASS");
    }
    else
    {
      puts("FAIL (returned 0)");
      status ++;
    }
  }
  else
  {
    const char	*filename;		/* PPD filename */
    struct stat	fileinfo;		/* File information */


    if (!strncmp(argv[1], "-d", 2))
    {
      const char *printer;		/* Printer name */

      if (argv[1][2])
	printer = argv[1] + 2;
      else if (argv[2])
	printer = argv[2];
      else
      {
        puts("Usage: ./testppd -d printer");
	return (1);
      }

      filename = cupsGetPPD(printer);

      if (!filename)
      {
        printf("%s: %s\n", printer, cupsLastErrorString());
        return (1);
      }
    }
    else
      filename = argv[1];

    if (lstat(filename, &fileinfo))
    {
      printf("%s: %s\n", filename, strerror(errno));
      return (1);
    }

    if (S_ISLNK(fileinfo.st_mode))
    {
      char	realfile[1024];		/* Real file path */
      ssize_t	realsize;		/* Size of real file path */


      if ((realsize = readlink(filename, realfile, sizeof(realfile) - 1)) < 0)
        strlcpy(realfile, "Unknown", sizeof(realfile));
      else
        realfile[realsize] = '\0';

      if (stat(realfile, &fileinfo))
	printf("%s: symlink to \"%s\", %s\n", filename, realfile,
	       strerror(errno));
      else
	printf("%s: symlink to \"%s\", %ld bytes\n", filename, realfile,
	       (long)fileinfo.st_size);
    }
    else
      printf("%s: regular file, %ld bytes\n", filename, (long)fileinfo.st_size);

    if ((ppd = ppdOpenFile(filename)) == NULL)
    {
      ppd_status_t	err;		/* Last error in file */
      int		line;		/* Line number in file */


      status ++;
      err = ppdLastError(&line);

      printf("%s: %s on line %d\n", argv[1], ppdErrorString(err), line);
    }
    else
    {
      int		j, k;		/* Looping vars */
      ppd_group_t	*group;		/* Option group */
      ppd_option_t	*option;	/* Option */
      ppd_coption_t	*coption;	/* Custom option */
      ppd_cparam_t	*cparam;	/* Custom parameter */
      ppd_const_t	*c;		/* UIConstraints */
      char		lang[255],	/* LANG environment variable */
			lc_all[255],	/* LC_ALL environment variable */
			lc_ctype[255],	/* LC_CTYPE environment variable */
			lc_messages[255];/* LC_MESSAGES environment variable */


      if (argc > 2)
      {
        snprintf(lang, sizeof(lang), "LANG=%s", argv[2]);
	putenv(lang);
        snprintf(lc_all, sizeof(lc_all), "LC_ALL=%s", argv[2]);
	putenv(lc_all);
        snprintf(lc_ctype, sizeof(lc_ctype), "LC_CTYPE=%s", argv[2]);
	putenv(lc_ctype);
        snprintf(lc_messages, sizeof(lc_messages), "LC_MESSAGES=%s", argv[2]);
	putenv(lc_messages);
      }

      ppdLocalize(ppd);
      ppdMarkDefaults(ppd);

      if (argc > 3)
      {
        text = ppdLocalizeIPPReason(ppd, argv[3], NULL, buffer, sizeof(buffer));
	printf("ppdLocalizeIPPReason(%s)=%s\n", argv[3],
	       text ? text : "(null)");
	return (text == NULL);
      }

      for (i = ppd->num_groups, group = ppd->groups;
	   i > 0;
	   i --, group ++)
      {
	printf("%s (%s):\n", group->name, group->text);

	for (j = group->num_options, option = group->options;
	     j > 0;
	     j --, option ++)
	{
	  printf("    %s (%s):\n", option->keyword, option->text);

	  for (k = 0; k < option->num_choices; k ++)
	    printf("        - %s%s (%s)\n",
	           option->choices[k].marked ? "*" : "",
		   option->choices[k].choice, option->choices[k].text);

          if ((coption = ppdFindCustomOption(ppd, option->keyword)) != NULL)
	  {
	    for (cparam = (ppd_cparam_t *)cupsArrayFirst(coption->params);
	         cparam;
		 cparam = (ppd_cparam_t *)cupsArrayNext(coption->params))
            {
	      switch (cparam->type)
	      {
	        case PPD_CUSTOM_CURVE :
		    printf("              %s(%s): PPD_CUSTOM_CURVE (%g to %g)\n",
		           cparam->name, cparam->text,
			   cparam->minimum.custom_curve,
			   cparam->maximum.custom_curve);
		    break;

	        case PPD_CUSTOM_INT :
		    printf("              %s(%s): PPD_CUSTOM_INT (%d to %d)\n",
		           cparam->name, cparam->text,
			   cparam->minimum.custom_int,
			   cparam->maximum.custom_int);
		    break;

	        case PPD_CUSTOM_INVCURVE :
		    printf("              %s(%s): PPD_CUSTOM_INVCURVE (%g to %g)\n",
		           cparam->name, cparam->text,
			   cparam->minimum.custom_invcurve,
			   cparam->maximum.custom_invcurve);
		    break;

	        case PPD_CUSTOM_PASSCODE :
		    printf("              %s(%s): PPD_CUSTOM_PASSCODE (%d to %d)\n",
		           cparam->name, cparam->text,
			   cparam->minimum.custom_passcode,
			   cparam->maximum.custom_passcode);
		    break;

	        case PPD_CUSTOM_PASSWORD :
		    printf("              %s(%s): PPD_CUSTOM_PASSWORD (%d to %d)\n",
		           cparam->name, cparam->text,
			   cparam->minimum.custom_password,
			   cparam->maximum.custom_password);
		    break;

	        case PPD_CUSTOM_POINTS :
		    printf("              %s(%s): PPD_CUSTOM_POINTS (%g to %g)\n",
		           cparam->name, cparam->text,
			   cparam->minimum.custom_points,
			   cparam->maximum.custom_points);
		    break;

	        case PPD_CUSTOM_REAL :
		    printf("              %s(%s): PPD_CUSTOM_REAL (%g to %g)\n",
		           cparam->name, cparam->text,
			   cparam->minimum.custom_real,
			   cparam->maximum.custom_real);
		    break;

	        case PPD_CUSTOM_STRING :
		    printf("              %s(%s): PPD_CUSTOM_STRING (%d to %d)\n",
		           cparam->name, cparam->text,
			   cparam->minimum.custom_string,
			   cparam->maximum.custom_string);
		    break;
	      }
	    }
	  }
	}
      }

      puts("\nSizes:");
      for (i = ppd->num_sizes, size = ppd->sizes; i > 0; i --, size ++)
        printf("    %s = %gx%g, [%g %g %g %g]\n", size->name, size->width,
	       size->length, size->left, size->bottom, size->right, size->top);

      puts("\nConstraints:");

      for (i = ppd->num_consts, c = ppd->consts; i > 0; i --, c ++)
        printf("    *UIConstraints: *%s %s *%s %s\n", c->option1, c->choice1,
	       c->option2, c->choice2);
      if (ppd->num_consts == 0)
        puts("    NO CONSTRAINTS");

      puts("\nFilters:");

      for (i = 0; i < ppd->num_filters; i ++)
        printf("    %s\n", ppd->filters[i]);

      if (ppd->num_filters == 0)
        puts("    NO FILTERS");

      puts("\nAttributes:");

      for (attr = (ppd_attr_t *)cupsArrayFirst(ppd->sorted_attrs);
           attr;
	   attr = (ppd_attr_t *)cupsArrayNext(ppd->sorted_attrs))
        printf("    *%s %s/%s: \"%s\"\n", attr->name, attr->spec,
	       attr->text, attr->value ? attr->value : "");

      puts("\nPPD Cache:");
      if ((pc = _ppdCacheCreateWithPPD(ppd)) == NULL)
        printf("    Unable to create: %s\n", cupsLastErrorString());
      else
      {
        _ppdCacheWriteFile(pc, "t.cache", NULL);
        puts("    Wrote t.cache.");
      }
    }

    if (!strncmp(argv[1], "-d", 2))
      unlink(filename);
  }

#ifdef __APPLE__
  if (getenv("MallocStackLogging") && getenv("MallocStackLoggingNoCompact"))
  {
    char	command[1024];		/* malloc_history command */

    snprintf(command, sizeof(command), "malloc_history %d -all_by_size",
	     getpid());
    fflush(stdout);
    system(command);
  }
#endif /* __APPLE__ */

  ppdClose(ppd);

  return (status);
}