/src/cups/cups/ppd-attr.c
Line | Count | Source (jump to first uncovered line) |
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 | 0 | { |
33 | 0 | ppd_attr_t key, /* Search key */ |
34 | 0 | *attr; /* Current attribute */ |
35 | | |
36 | |
|
37 | 0 | DEBUG_printf(("2ppdFindAttr(ppd=%p, name=\"%s\", spec=\"%s\")", ppd, name, |
38 | 0 | spec)); |
39 | | |
40 | | /* |
41 | | * Range check input... |
42 | | */ |
43 | |
|
44 | 0 | if (!ppd || !name || ppd->num_attrs == 0) |
45 | 0 | return (NULL); |
46 | | |
47 | | /* |
48 | | * Search for a matching attribute... |
49 | | */ |
50 | | |
51 | 0 | memset(&key, 0, sizeof(key)); |
52 | 0 | strlcpy(key.name, name, sizeof(key.name)); |
53 | | |
54 | | /* |
55 | | * Return the first matching attribute, if any... |
56 | | */ |
57 | |
|
58 | 0 | if ((attr = (ppd_attr_t *)cupsArrayFind(ppd->sorted_attrs, &key)) != NULL) |
59 | 0 | { |
60 | 0 | if (spec) |
61 | 0 | { |
62 | | /* |
63 | | * Loop until we find the first matching attribute for "spec"... |
64 | | */ |
65 | |
|
66 | 0 | while (attr && _cups_strcasecmp(spec, attr->spec)) |
67 | 0 | { |
68 | 0 | if ((attr = (ppd_attr_t *)cupsArrayNext(ppd->sorted_attrs)) != NULL && |
69 | 0 | _cups_strcasecmp(attr->name, name)) |
70 | 0 | attr = NULL; |
71 | 0 | } |
72 | 0 | } |
73 | 0 | } |
74 | |
|
75 | 0 | return (attr); |
76 | 0 | } |
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 | 0 | { |
90 | 0 | ppd_attr_t *attr; /* Current attribute */ |
91 | | |
92 | | |
93 | | /* |
94 | | * Range check input... |
95 | | */ |
96 | |
|
97 | 0 | if (!ppd || !name || ppd->num_attrs == 0) |
98 | 0 | return (NULL); |
99 | | |
100 | | /* |
101 | | * See if there are more attributes to return... |
102 | | */ |
103 | | |
104 | 0 | while ((attr = (ppd_attr_t *)cupsArrayNext(ppd->sorted_attrs)) != NULL) |
105 | 0 | { |
106 | | /* |
107 | | * Check the next attribute to see if it is a match... |
108 | | */ |
109 | |
|
110 | 0 | if (_cups_strcasecmp(attr->name, name)) |
111 | 0 | { |
112 | | /* |
113 | | * Nope, reset the current pointer to the end of the array... |
114 | | */ |
115 | |
|
116 | 0 | cupsArrayIndex(ppd->sorted_attrs, cupsArrayCount(ppd->sorted_attrs)); |
117 | |
|
118 | 0 | return (NULL); |
119 | 0 | } |
120 | | |
121 | 0 | if (!spec || !_cups_strcasecmp(attr->spec, spec)) |
122 | 0 | break; |
123 | 0 | } |
124 | | |
125 | | /* |
126 | | * Return the next attribute's value... |
127 | | */ |
128 | | |
129 | 0 | return (attr); |
130 | 0 | } |
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 | 0 | { |
146 | 0 | char *bufptr; /* Pointer into buffer */ |
147 | | |
148 | |
|
149 | 0 | if (!make_and_model || !buffer || bufsize < 1) |
150 | 0 | { |
151 | 0 | if (buffer) |
152 | 0 | *buffer = '\0'; |
153 | |
|
154 | 0 | return (NULL); |
155 | 0 | } |
156 | | |
157 | | /* |
158 | | * Skip leading whitespace... |
159 | | */ |
160 | | |
161 | 0 | while (_cups_isspace(*make_and_model)) |
162 | 0 | make_and_model ++; |
163 | | |
164 | | /* |
165 | | * Remove parenthesis and add manufacturers as needed... |
166 | | */ |
167 | |
|
168 | 0 | if (make_and_model[0] == '(') |
169 | 0 | { |
170 | 0 | strlcpy(buffer, make_and_model + 1, bufsize); |
171 | |
|
172 | 0 | if ((bufptr = strrchr(buffer, ')')) != NULL) |
173 | 0 | *bufptr = '\0'; |
174 | 0 | } |
175 | 0 | else if (!_cups_strncasecmp(make_and_model, "XPrint", 6)) |
176 | 0 | { |
177 | | /* |
178 | | * Xerox XPrint... |
179 | | */ |
180 | |
|
181 | 0 | snprintf(buffer, bufsize, "Xerox %s", make_and_model); |
182 | 0 | } |
183 | 0 | else if (!_cups_strncasecmp(make_and_model, "Eastman", 7)) |
184 | 0 | { |
185 | | /* |
186 | | * Kodak... |
187 | | */ |
188 | |
|
189 | 0 | snprintf(buffer, bufsize, "Kodak %s", make_and_model + 7); |
190 | 0 | } |
191 | 0 | else if (!_cups_strncasecmp(make_and_model, "laserwriter", 11)) |
192 | 0 | { |
193 | | /* |
194 | | * Apple LaserWriter... |
195 | | */ |
196 | |
|
197 | 0 | snprintf(buffer, bufsize, "Apple LaserWriter%s", make_and_model + 11); |
198 | 0 | } |
199 | 0 | else if (!_cups_strncasecmp(make_and_model, "colorpoint", 10)) |
200 | 0 | { |
201 | | /* |
202 | | * Seiko... |
203 | | */ |
204 | |
|
205 | 0 | snprintf(buffer, bufsize, "Seiko %s", make_and_model); |
206 | 0 | } |
207 | 0 | else if (!_cups_strncasecmp(make_and_model, "fiery", 5)) |
208 | 0 | { |
209 | | /* |
210 | | * EFI... |
211 | | */ |
212 | |
|
213 | 0 | snprintf(buffer, bufsize, "EFI %s", make_and_model); |
214 | 0 | } |
215 | 0 | else if (!_cups_strncasecmp(make_and_model, "ps ", 3) || |
216 | 0 | !_cups_strncasecmp(make_and_model, "colorpass", 9)) |
217 | 0 | { |
218 | | /* |
219 | | * Canon... |
220 | | */ |
221 | |
|
222 | 0 | snprintf(buffer, bufsize, "Canon %s", make_and_model); |
223 | 0 | } |
224 | 0 | else if (!_cups_strncasecmp(make_and_model, "designjet", 9) || |
225 | 0 | !_cups_strncasecmp(make_and_model, "deskjet", 7)) |
226 | 0 | { |
227 | | /* |
228 | | * HP... |
229 | | */ |
230 | |
|
231 | 0 | snprintf(buffer, bufsize, "HP %s", make_and_model); |
232 | 0 | } |
233 | 0 | else |
234 | 0 | strlcpy(buffer, make_and_model, bufsize); |
235 | | |
236 | | /* |
237 | | * Clean up the make... |
238 | | */ |
239 | |
|
240 | 0 | if (!_cups_strncasecmp(buffer, "agfa", 4)) |
241 | 0 | { |
242 | | /* |
243 | | * Replace with AGFA (all uppercase)... |
244 | | */ |
245 | |
|
246 | 0 | buffer[0] = 'A'; |
247 | 0 | buffer[1] = 'G'; |
248 | 0 | buffer[2] = 'F'; |
249 | 0 | buffer[3] = 'A'; |
250 | 0 | } |
251 | 0 | else if (!_cups_strncasecmp(buffer, "Hewlett-Packard hp ", 19)) |
252 | 0 | { |
253 | | /* |
254 | | * Just put "HP" on the front... |
255 | | */ |
256 | |
|
257 | 0 | buffer[0] = 'H'; |
258 | 0 | buffer[1] = 'P'; |
259 | 0 | _cups_strcpy(buffer + 2, buffer + 18); |
260 | 0 | } |
261 | 0 | else if (!_cups_strncasecmp(buffer, "Hewlett-Packard ", 16)) |
262 | 0 | { |
263 | | /* |
264 | | * Just put "HP" on the front... |
265 | | */ |
266 | |
|
267 | 0 | buffer[0] = 'H'; |
268 | 0 | buffer[1] = 'P'; |
269 | 0 | _cups_strcpy(buffer + 2, buffer + 15); |
270 | 0 | } |
271 | 0 | else if (!_cups_strncasecmp(buffer, "Lexmark International", 21)) |
272 | 0 | { |
273 | | /* |
274 | | * Strip "International"... |
275 | | */ |
276 | |
|
277 | 0 | _cups_strcpy(buffer + 8, buffer + 21); |
278 | 0 | } |
279 | 0 | else if (!_cups_strncasecmp(buffer, "herk", 4)) |
280 | 0 | { |
281 | | /* |
282 | | * Replace with LHAG... |
283 | | */ |
284 | |
|
285 | 0 | buffer[0] = 'L'; |
286 | 0 | buffer[1] = 'H'; |
287 | 0 | buffer[2] = 'A'; |
288 | 0 | buffer[3] = 'G'; |
289 | 0 | } |
290 | 0 | else if (!_cups_strncasecmp(buffer, "linotype", 8)) |
291 | 0 | { |
292 | | /* |
293 | | * Replace with LHAG... |
294 | | */ |
295 | |
|
296 | 0 | buffer[0] = 'L'; |
297 | 0 | buffer[1] = 'H'; |
298 | 0 | buffer[2] = 'A'; |
299 | 0 | buffer[3] = 'G'; |
300 | 0 | _cups_strcpy(buffer + 4, buffer + 8); |
301 | 0 | } |
302 | | |
303 | | /* |
304 | | * Remove trailing whitespace and return... |
305 | | */ |
306 | |
|
307 | 0 | for (bufptr = buffer + strlen(buffer) - 1; |
308 | 0 | bufptr >= buffer && _cups_isspace(*bufptr); |
309 | 0 | bufptr --); |
310 | |
|
311 | 0 | bufptr[1] = '\0'; |
312 | |
|
313 | 0 | return (buffer[0] ? buffer : NULL); |
314 | 0 | } |