• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 */
ppdFindAttr(ppd_file_t * ppd,const char * name,const char * spec)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 */
ppdFindNextAttr(ppd_file_t * ppd,const char * name,const char * spec)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 */
_ppdNormalizeMakeAndModel(const char * make_and_model,char * buffer,size_t bufsize)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