Home | History | Annotate | Download | only in cups
      1 /*
      2  * PPD model-specific attribute routines for CUPS.
      3  *
      4  * Copyright 2007-2015 by Apple Inc.
      5  * Copyright 1997-2006 by Easy Software Products.
      6  *
      7  * These coded instructions, statements, and computer programs are the
      8  * property of Apple Inc. and are protected by Federal copyright
      9  * law.  Distribution and use rights are outlined in the file "LICENSE.txt"
     10  * which should have been included with this file.  If this file is
     11  * missing or damaged, see the license at "http://www.cups.org/".
     12  */
     13 
     14 /*
     15  * Include necessary headers...
     16  */
     17 
     18 #include "cups-private.h"
     19 #include "ppd-private.h"
     20 
     21 
     22 /*
     23  * 'ppdFindAttr()' - Find the first matching attribute.
     24  *
     25  * @since CUPS 1.1.19/macOS 10.3@
     26  */
     27 
     28 ppd_attr_t *				/* O - Attribute or @code NULL@ if not found */
     29 ppdFindAttr(ppd_file_t *ppd,		/* I - PPD file data */
     30             const char *name,		/* I - Attribute name */
     31             const char *spec)		/* I - Specifier string or @code NULL@ */
     32 {
     33   ppd_attr_t	key,			/* Search key */
     34 		*attr;			/* Current attribute */
     35 
     36 
     37   DEBUG_printf(("2ppdFindAttr(ppd=%p, name=\"%s\", spec=\"%s\")", ppd, name,
     38                 spec));
     39 
     40  /*
     41   * Range check input...
     42   */
     43 
     44   if (!ppd || !name || ppd->num_attrs == 0)
     45     return (NULL);
     46 
     47  /*
     48   * Search for a matching attribute...
     49   */
     50 
     51   memset(&key, 0, sizeof(key));
     52   strlcpy(key.name, name, sizeof(key.name));
     53 
     54  /*
     55   * Return the first matching attribute, if any...
     56   */
     57 
     58   if ((attr = (ppd_attr_t *)cupsArrayFind(ppd->sorted_attrs, &key)) != NULL)
     59   {
     60     if (spec)
     61     {
     62      /*
     63       * Loop until we find the first matching attribute for "spec"...
     64       */
     65 
     66       while (attr && _cups_strcasecmp(spec, attr->spec))
     67       {
     68         if ((attr = (ppd_attr_t *)cupsArrayNext(ppd->sorted_attrs)) != NULL &&
     69 	    _cups_strcasecmp(attr->name, name))
     70 	  attr = NULL;
     71       }
     72     }
     73   }
     74 
     75   return (attr);
     76 }
     77 
     78 
     79 /*
     80  * 'ppdFindNextAttr()' - Find the next matching attribute.
     81  *
     82  * @since CUPS 1.1.19/macOS 10.3@
     83  */
     84 
     85 ppd_attr_t *				/* O - Attribute or @code NULL@ if not found */
     86 ppdFindNextAttr(ppd_file_t *ppd,	/* I - PPD file data */
     87                 const char *name,	/* I - Attribute name */
     88 		const char *spec)	/* I - Specifier string or @code NULL@ */
     89 {
     90   ppd_attr_t	*attr;			/* Current attribute */
     91 
     92 
     93  /*
     94   * Range check input...
     95   */
     96 
     97   if (!ppd || !name || ppd->num_attrs == 0)
     98     return (NULL);
     99 
    100  /*
    101   * See if there are more attributes to return...
    102   */
    103 
    104   while ((attr = (ppd_attr_t *)cupsArrayNext(ppd->sorted_attrs)) != NULL)
    105   {
    106    /*
    107     * Check the next attribute to see if it is a match...
    108     */
    109 
    110     if (_cups_strcasecmp(attr->name, name))
    111     {
    112      /*
    113       * Nope, reset the current pointer to the end of the array...
    114       */
    115 
    116       cupsArrayIndex(ppd->sorted_attrs, cupsArrayCount(ppd->sorted_attrs));
    117 
    118       return (NULL);
    119     }
    120 
    121     if (!spec || !_cups_strcasecmp(attr->spec, spec))
    122       break;
    123   }
    124 
    125  /*
    126   * Return the next attribute's value...
    127   */
    128 
    129   return (attr);
    130 }
    131 
    132 
    133 /*
    134  * '_ppdNormalizeMakeAndModel()' - Normalize a product/make-and-model string.
    135  *
    136  * This function tries to undo the mistakes made by many printer manufacturers
    137  * to produce a clean make-and-model string we can use.
    138  */
    139 
    140 char *					/* O - Normalized make-and-model string or NULL on error */
    141 _ppdNormalizeMakeAndModel(
    142     const char *make_and_model,		/* I - Original make-and-model string */
    143     char       *buffer,			/* I - String buffer */
    144     size_t     bufsize)			/* I - Size of string buffer */
    145 {
    146   char	*bufptr;			/* Pointer into buffer */
    147 
    148 
    149   if (!make_and_model || !buffer || bufsize < 1)
    150   {
    151     if (buffer)
    152       *buffer = '\0';
    153 
    154     return (NULL);
    155   }
    156 
    157  /*
    158   * Skip leading whitespace...
    159   */
    160 
    161   while (_cups_isspace(*make_and_model))
    162     make_and_model ++;
    163 
    164  /*
    165   * Remove parenthesis and add manufacturers as needed...
    166   */
    167 
    168   if (make_and_model[0] == '(')
    169   {
    170     strlcpy(buffer, make_and_model + 1, bufsize);
    171 
    172     if ((bufptr = strrchr(buffer, ')')) != NULL)
    173       *bufptr = '\0';
    174   }
    175   else if (!_cups_strncasecmp(make_and_model, "XPrint", 6))
    176   {
    177    /*
    178     * Xerox XPrint...
    179     */
    180 
    181     snprintf(buffer, bufsize, "Xerox %s", make_and_model);
    182   }
    183   else if (!_cups_strncasecmp(make_and_model, "Eastman", 7))
    184   {
    185    /*
    186     * Kodak...
    187     */
    188 
    189     snprintf(buffer, bufsize, "Kodak %s", make_and_model + 7);
    190   }
    191   else if (!_cups_strncasecmp(make_and_model, "laserwriter", 11))
    192   {
    193    /*
    194     * Apple LaserWriter...
    195     */
    196 
    197     snprintf(buffer, bufsize, "Apple LaserWriter%s", make_and_model + 11);
    198   }
    199   else if (!_cups_strncasecmp(make_and_model, "colorpoint", 10))
    200   {
    201    /*
    202     * Seiko...
    203     */
    204 
    205     snprintf(buffer, bufsize, "Seiko %s", make_and_model);
    206   }
    207   else if (!_cups_strncasecmp(make_and_model, "fiery", 5))
    208   {
    209    /*
    210     * EFI...
    211     */
    212 
    213     snprintf(buffer, bufsize, "EFI %s", make_and_model);
    214   }
    215   else if (!_cups_strncasecmp(make_and_model, "ps ", 3) ||
    216 	   !_cups_strncasecmp(make_and_model, "colorpass", 9))
    217   {
    218    /*
    219     * Canon...
    220     */
    221 
    222     snprintf(buffer, bufsize, "Canon %s", make_and_model);
    223   }
    224   else if (!_cups_strncasecmp(make_and_model, "designjet", 9) ||
    225            !_cups_strncasecmp(make_and_model, "deskjet", 7))
    226   {
    227    /*
    228     * HP...
    229     */
    230 
    231     snprintf(buffer, bufsize, "HP %s", make_and_model);
    232   }
    233   else
    234     strlcpy(buffer, make_and_model, bufsize);
    235 
    236  /*
    237   * Clean up the make...
    238   */
    239 
    240   if (!_cups_strncasecmp(buffer, "agfa", 4))
    241   {
    242    /*
    243     * Replace with AGFA (all uppercase)...
    244     */
    245 
    246     buffer[0] = 'A';
    247     buffer[1] = 'G';
    248     buffer[2] = 'F';
    249     buffer[3] = 'A';
    250   }
    251   else if (!_cups_strncasecmp(buffer, "Hewlett-Packard hp ", 19))
    252   {
    253    /*
    254     * Just put "HP" on the front...
    255     */
    256 
    257     buffer[0] = 'H';
    258     buffer[1] = 'P';
    259     _cups_strcpy(buffer + 2, buffer + 18);
    260   }
    261   else if (!_cups_strncasecmp(buffer, "Hewlett-Packard ", 16))
    262   {
    263    /*
    264     * Just put "HP" on the front...
    265     */
    266 
    267     buffer[0] = 'H';
    268     buffer[1] = 'P';
    269     _cups_strcpy(buffer + 2, buffer + 15);
    270   }
    271   else if (!_cups_strncasecmp(buffer, "Lexmark International", 21))
    272   {
    273    /*
    274     * Strip "International"...
    275     */
    276 
    277     _cups_strcpy(buffer + 8, buffer + 21);
    278   }
    279   else if (!_cups_strncasecmp(buffer, "herk", 4))
    280   {
    281    /*
    282     * Replace with LHAG...
    283     */
    284 
    285     buffer[0] = 'L';
    286     buffer[1] = 'H';
    287     buffer[2] = 'A';
    288     buffer[3] = 'G';
    289   }
    290   else if (!_cups_strncasecmp(buffer, "linotype", 8))
    291   {
    292    /*
    293     * Replace with LHAG...
    294     */
    295 
    296     buffer[0] = 'L';
    297     buffer[1] = 'H';
    298     buffer[2] = 'A';
    299     buffer[3] = 'G';
    300     _cups_strcpy(buffer + 4, buffer + 8);
    301   }
    302 
    303  /*
    304   * Remove trailing whitespace and return...
    305   */
    306 
    307   for (bufptr = buffer + strlen(buffer) - 1;
    308        bufptr >= buffer && _cups_isspace(*bufptr);
    309        bufptr --);
    310 
    311   bufptr[1] = '\0';
    312 
    313   return (buffer[0] ? buffer : NULL);
    314 }
    315