]> git.ipfire.org Git - thirdparty/cups.git/blame - backend/snmp-supplies.c
Merge changes from CUPS 1.5svn-r8857.
[thirdparty/cups.git] / backend / snmp-supplies.c
CommitLineData
568fa3fa
MS
1/*
2 * "$Id$"
3 *
4 * SNMP supplies functions for the Common UNIX Printing System (CUPS).
5 *
d1c13e16 6 * Copyright 2008-2009 by Apple Inc.
568fa3fa
MS
7 *
8 * These coded instructions, statements, and computer programs are the
9 * property of Apple Inc. and are protected by Federal copyright
10 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
11 * "LICENSE" which should have been included with this file. If this
12 * file is missing or damaged, see the license at "http://www.cups.org/".
13 *
14 * This file is subject to the Apple OS-Developed Software exception.
15 *
16 * Contents:
17 *
18 * backendSNMPSupplies() - Get the current supplies for a device.
19 * backend_init_supplies() - Initialize the supplies list.
68b10830
MS
20 * backend_walk_cb() - Interpret the supply value responses.
21 * utf16_to_utf8() - Convert UTF-16 text to UTF-8.
568fa3fa
MS
22 */
23
24/*
25 * Include necessary headers.
26 */
27
28#include "backend-private.h"
29#include <cups/array.h>
30
31
32/*
33 * Local constants...
34 */
35
36#define CUPS_MAX_SUPPLIES 32 /* Maximum number of supplies for a printer */
68b10830 37#define CUPS_SUPPLY_TIMEOUT 2.0 /* Timeout for SNMP lookups */
568fa3fa
MS
38
39
40/*
41 * Local structures...
42 */
43
745129be 44typedef struct /**** Printer supply data ****/
568fa3fa
MS
45{
46 char name[CUPS_SNMP_MAX_STRING], /* Name of supply */
47 color[8]; /* Color: "#RRGGBB" or "none" */
48 int colorant, /* Colorant index */
49 type, /* Supply type */
50 max_capacity, /* Maximum capacity */
51 level; /* Current level value */
52} backend_supplies_t;
53
745129be
MS
54typedef struct /**** Printer state table ****/
55{
56 int bit; /* State bit */
57 const char *keyword; /* IPP printer-state-reasons keyword */
58} backend_state_t;
59
568fa3fa
MS
60
61/*
62 * Local globals...
63 */
64
65static http_addr_t current_addr; /* Current address */
745129be
MS
66static int current_state = -1;
67 /* Current device state bits */
68b10830 68static int charset = -1; /* Character set for supply names */
568fa3fa
MS
69static int num_supplies = 0;
70 /* Number of supplies found */
71static backend_supplies_t supplies[CUPS_MAX_SUPPLIES];
72 /* Supply information */
73
74static const int hrDeviceDescr[] =
75 { CUPS_OID_hrDeviceDescr, 1, -1 };
76 /* Device description OID */
77static const int hrPrinterStatus[] =
78 { CUPS_OID_hrPrinterStatus, 1, -1 };
79 /* Current state OID */
80static const int hrPrinterDetectedErrorState[] =
81 { CUPS_OID_hrPrinterDetectedErrorState, 1, -1 };
82 /* Current printer state bits OID */
68b10830
MS
83static const int prtGeneralCurrentLocalization[] =
84 { CUPS_OID_prtGeneralCurrentLocalization, 1, -1 };
85static const int prtLocalizationCharacterSet[] =
86 { CUPS_OID_prtLocalizationCharacterSet, 1, 1, -1 },
87 prtLocalizationCharacterSetOffset =
88 (sizeof(prtLocalizationCharacterSet) /
89 sizeof(prtLocalizationCharacterSet[0]));
568fa3fa
MS
90static const int prtMarkerColorantValue[] =
91 { CUPS_OID_prtMarkerColorantValue, -1 },
92 /* Colorant OID */
93 prtMarkerColorantValueOffset =
94 (sizeof(prtMarkerColorantValue) /
95 sizeof(prtMarkerColorantValue[0]));
96 /* Offset to colorant index */
97static const int prtMarkerLifeCount[] =
98 { CUPS_OID_prtMarkerLifeCount, 1, 1, -1 };
99 /* Page counter OID */
100static const int prtMarkerSuppliesEntry[] =
101 { CUPS_OID_prtMarkerSuppliesEntry, -1 };
102 /* Supplies OID */
103static const int prtMarkerSuppliesColorantIndex[] =
104 { CUPS_OID_prtMarkerSuppliesColorantIndex, -1 },
105 /* Colorant index OID */
106 prtMarkerSuppliesColorantIndexOffset =
107 (sizeof(prtMarkerSuppliesColorantIndex) /
108 sizeof(prtMarkerSuppliesColorantIndex[0]));
109 /* Offset to supply index */
110static const int prtMarkerSuppliesDescription[] =
111 { CUPS_OID_prtMarkerSuppliesDescription, -1 },
112 /* Description OID */
113 prtMarkerSuppliesDescriptionOffset =
114 (sizeof(prtMarkerSuppliesDescription) /
115 sizeof(prtMarkerSuppliesDescription[0]));
116 /* Offset to supply index */
117static const int prtMarkerSuppliesLevel[] =
118 { CUPS_OID_prtMarkerSuppliesLevel, -1 },
119 /* Level OID */
120 prtMarkerSuppliesLevelOffset =
121 (sizeof(prtMarkerSuppliesLevel) /
122 sizeof(prtMarkerSuppliesLevel[0]));
123 /* Offset to supply index */
124static const int prtMarkerSuppliesMaxCapacity[] =
125 { CUPS_OID_prtMarkerSuppliesMaxCapacity, -1 },
126 /* Max capacity OID */
127 prtMarkerSuppliesMaxCapacityOffset =
128 (sizeof(prtMarkerSuppliesMaxCapacity) /
129 sizeof(prtMarkerSuppliesMaxCapacity[0]));
130 /* Offset to supply index */
131static const int prtMarkerSuppliesType[] =
132 { CUPS_OID_prtMarkerSuppliesType, -1 },
133 /* Type OID */
134 prtMarkerSuppliesTypeOffset =
135 (sizeof(prtMarkerSuppliesType) /
136 sizeof(prtMarkerSuppliesType[0]));
137 /* Offset to supply index */
138
745129be
MS
139static const backend_state_t const printer_states[] =
140 {
141 { CUPS_TC_lowPaper, "media-low-report" },
142 { CUPS_TC_noPaper | CUPS_TC_inputTrayEmpty, "media-empty-warning" },
143 { CUPS_TC_lowToner, "toner-low-report" },
144 { CUPS_TC_noToner, "toner-empty-warning" },
145 { CUPS_TC_doorOpen, "door-open-report" },
146 { CUPS_TC_jammed, "media-jam-warning" },
147 /* { CUPS_TC_offline, "offline-report" }, */ /* unreliable */
e07d4801 148 /* { CUPS_TC_serviceRequested | CUPS_TC_overduePreventMaint, "service-needed-warning" }, */ /* unreliable */
745129be
MS
149 { CUPS_TC_inputTrayMissing, "input-tray-missing-warning" },
150 { CUPS_TC_outputTrayMissing, "output-tray-missing-warning" },
151 { CUPS_TC_markerSupplyMissing, "marker-supply-missing-warning" },
152 { CUPS_TC_outputNearFull, "output-area-almost-full-report" },
153 { CUPS_TC_outputFull, "output-area-full-warning" }
154 };
155
568fa3fa
MS
156
157/*
158 * Local functions...
159 */
160
161static void backend_init_supplies(int snmp_fd, http_addr_t *addr);
162static void backend_walk_cb(cups_snmp_t *packet, void *data);
68b10830
MS
163static void utf16_to_utf8(cups_utf8_t *dst, const unsigned char *src,
164 size_t srcsize, size_t dstsize, int le);
568fa3fa
MS
165
166
167/*
168 * 'backendSNMPSupplies()' - Get the current supplies for a device.
169 */
170
171int /* O - 0 on success, -1 on error */
172backendSNMPSupplies(
173 int snmp_fd, /* I - SNMP socket */
174 http_addr_t *addr, /* I - Printer address */
175 int *page_count, /* O - Page count */
176 int *printer_state) /* O - Printer state */
177{
178 if (!httpAddrEqual(addr, &current_addr))
179 backend_init_supplies(snmp_fd, addr);
180 else if (num_supplies > 0)
7a14d768 181 _cupsSNMPWalk(snmp_fd, &current_addr, CUPS_SNMP_VERSION_1,
68b10830
MS
182 _cupsSNMPDefaultCommunity(), prtMarkerSuppliesLevel,
183 CUPS_SUPPLY_TIMEOUT, backend_walk_cb, NULL);
568fa3fa
MS
184
185 if (page_count)
186 *page_count = -1;
187
188 if (printer_state)
189 *printer_state = -1;
190
191 if (num_supplies > 0)
192 {
745129be
MS
193 int i, /* Looping var */
194 new_state, /* New state value */
195 change_state; /* State change */
568fa3fa
MS
196 char value[CUPS_MAX_SUPPLIES * 4],
197 /* marker-levels value string */
198 *ptr; /* Pointer into value string */
199 cups_snmp_t packet; /* SNMP response packet */
745129be 200
568fa3fa
MS
201
202 /*
203 * Generate the marker-levels value string...
204 */
205
206 for (i = 0, ptr = value; i < num_supplies; i ++, ptr += strlen(ptr))
207 {
208 if (i)
209 *ptr++ = ',';
210
06d4e77b
MS
211 if (supplies[i].max_capacity > 0)
212 sprintf(ptr, "%d", 100 * supplies[i].level / supplies[i].max_capacity);
213 else
214 strcpy(ptr, "-1");
568fa3fa
MS
215 }
216
217 fprintf(stderr, "ATTR: marker-levels=%s\n", value);
218
219 /*
220 * Get the current printer status bits...
221 */
222
7a14d768
MS
223 if (!_cupsSNMPWrite(snmp_fd, addr, CUPS_SNMP_VERSION_1,
224 _cupsSNMPDefaultCommunity(), CUPS_ASN1_GET_REQUEST, 1,
568fa3fa
MS
225 hrPrinterDetectedErrorState))
226 return (-1);
227
68b10830 228 if (!_cupsSNMPRead(snmp_fd, &packet, CUPS_SUPPLY_TIMEOUT) ||
568fa3fa
MS
229 packet.object_type != CUPS_ASN1_OCTET_STRING)
230 return (-1);
231
18ecb428
MS
232 if (packet.object_value.string.num_bytes == 2)
233 new_state = (packet.object_value.string.bytes[0] << 8) |
234 packet.object_value.string.bytes[1];
235 else
236 new_state = 0;
568fa3fa 237
745129be
MS
238 if (current_state < 0)
239 change_state = 0xffff;
568fa3fa 240 else
745129be 241 change_state = current_state ^ new_state;
568fa3fa 242
745129be
MS
243 for (i = 0;
244 i < (int)(sizeof(printer_states) / sizeof(printer_states[0]));
245 i ++)
246 if (change_state & printer_states[i].bit)
247 fprintf(stderr, "STATE: %c%s\n",
248 (new_state & printer_states[i].bit) ? '+' : '-',
249 printer_states[i].keyword);
568fa3fa 250
745129be 251 current_state = new_state;
568fa3fa
MS
252
253 /*
254 * Get the current printer state...
255 */
256
257 if (printer_state)
258 {
7a14d768
MS
259 if (!_cupsSNMPWrite(snmp_fd, addr, CUPS_SNMP_VERSION_1,
260 _cupsSNMPDefaultCommunity(), CUPS_ASN1_GET_REQUEST, 1,
568fa3fa
MS
261 hrPrinterStatus))
262 return (-1);
263
68b10830 264 if (!_cupsSNMPRead(snmp_fd, &packet, CUPS_SUPPLY_TIMEOUT) ||
568fa3fa
MS
265 packet.object_type != CUPS_ASN1_INTEGER)
266 return (-1);
267
268 *printer_state = packet.object_value.integer;
269 }
270
271 /*
272 * Get the current page count...
273 */
274
275 if (page_count)
276 {
7a14d768
MS
277 if (!_cupsSNMPWrite(snmp_fd, addr, CUPS_SNMP_VERSION_1,
278 _cupsSNMPDefaultCommunity(), CUPS_ASN1_GET_REQUEST, 1,
568fa3fa
MS
279 prtMarkerLifeCount))
280 return (-1);
281
68b10830 282 if (!_cupsSNMPRead(snmp_fd, &packet, CUPS_SUPPLY_TIMEOUT) ||
568fa3fa
MS
283 packet.object_type != CUPS_ASN1_COUNTER)
284 return (-1);
285
286 *page_count = packet.object_value.counter;
287 }
288
289 return (0);
290 }
291 else
292 return (-1);
293}
294
295
296/*
297 * 'backend_init_supplies()' - Initialize the supplies list.
298 */
299
300static void
301backend_init_supplies(
302 int snmp_fd, /* I - SNMP socket */
303 http_addr_t *addr) /* I - Printer address */
304{
305 int i, /* Looping var */
306 type; /* Current marker type */
307 cups_file_t *cachefile; /* Cache file */
308 const char *cachedir; /* CUPS_CACHEDIR value */
309 char addrstr[1024], /* Address string */
310 cachefilename[1024], /* Cache filename */
311 description[CUPS_SNMP_MAX_STRING],
312 /* Device description string */
313 value[CUPS_MAX_SUPPLIES * (CUPS_SNMP_MAX_STRING * 2 + 3)],
314 /* Value string */
315 *ptr, /* Pointer into value string */
316 *name_ptr; /* Pointer into name string */
317 cups_snmp_t packet; /* SNMP response packet */
58dc1933
MS
318 ppd_file_t *ppd; /* PPD file for this queue */
319 ppd_attr_t *ppdattr; /* cupsSNMPSupplies attribute */
568fa3fa
MS
320 static const char * const types[] = /* Supply types */
321 {
322 "other",
323 "unknown",
324 "toner",
325 "wasteToner",
326 "ink",
327 "inkCartridge",
328 "inkRibbon",
329 "wasteInk",
330 "opc",
331 "developer",
332 "fuserOil",
333 "solidWax",
334 "ribbonWax",
335 "wasteWax",
336 "fuser",
337 "coronaWire",
338 "fuserOilWick",
339 "cleanerUnit",
340 "fuserCleaningPad",
341 "transferUnit",
342 "tonerCartridge",
343 "fuserOiler",
344 "water",
345 "wasteWater",
346 "glueWaterAdditive",
347 "wastePaper",
348 "bindingSupply",
349 "bandingSupply",
350 "stitchingWire",
351 "shrinkWrap",
352 "paperWrap",
353 "staples",
354 "inserts",
355 "covers"
356 };
357
358
359 /*
360 * Reset state information...
361 */
362
745129be
MS
363 current_addr = *addr;
364 current_state = -1;
365 num_supplies = -1;
68b10830 366 charset = -1;
568fa3fa
MS
367
368 memset(supplies, 0, sizeof(supplies));
369
58dc1933
MS
370 /*
371 * See if we should be getting supply levels via SNMP...
372 */
373
374 if ((ppd = ppdOpenFile(getenv("PPD"))) != NULL &&
375 (ppdattr = ppdFindAttr(ppd, "cupsSNMPSupplies", NULL)) != NULL &&
376 ppdattr->value && strcasecmp(ppdattr->value, "true"))
377 {
378 ppdClose(ppd);
379 return;
380 }
381
382 ppdClose(ppd);
383
568fa3fa
MS
384 /*
385 * Get the device description...
386 */
387
7a14d768
MS
388 if (!_cupsSNMPWrite(snmp_fd, addr, CUPS_SNMP_VERSION_1,
389 _cupsSNMPDefaultCommunity(), CUPS_ASN1_GET_REQUEST, 1,
568fa3fa
MS
390 hrDeviceDescr))
391 return;
392
68b10830 393 if (!_cupsSNMPRead(snmp_fd, &packet, CUPS_SUPPLY_TIMEOUT) ||
568fa3fa
MS
394 packet.object_type != CUPS_ASN1_OCTET_STRING)
395 {
396 strlcpy(description, "Unknown", sizeof(description));
397 num_supplies = 0;
398 }
399 else
d1c13e16
MS
400 strlcpy(description, (char *)packet.object_value.string.bytes,
401 sizeof(description));
568fa3fa 402
68b10830
MS
403 fprintf(stderr, "DEBUG2: hrDeviceDesc=\"%s\"\n", description);
404
568fa3fa
MS
405 /*
406 * See if we have already queried this device...
407 */
408
409 httpAddrString(addr, addrstr, sizeof(addrstr));
410
411 if ((cachedir = getenv("CUPS_CACHEDIR")) == NULL)
412 cachedir = CUPS_CACHEDIR;
413
414 snprintf(cachefilename, sizeof(cachefilename), "%s/%s.snmp", cachedir,
415 addrstr);
416
417 if ((cachefile = cupsFileOpen(cachefilename, "r")) != NULL)
418 {
419 /*
420 * Yes, read the cache file:
421 *
68b10830 422 * 2 num_supplies charset
568fa3fa
MS
423 * device description
424 * supply structures...
425 */
426
427 if (cupsFileGets(cachefile, value, sizeof(value)))
428 {
68b10830 429 if (sscanf(value, "2 %d%d", &num_supplies, &charset) == 2 &&
568fa3fa
MS
430 num_supplies <= CUPS_MAX_SUPPLIES &&
431 cupsFileGets(cachefile, value, sizeof(value)))
432 {
568fa3fa
MS
433 if (!strcmp(description, value))
434 cupsFileRead(cachefile, (char *)supplies,
435 num_supplies * sizeof(backend_supplies_t));
436 else
68b10830 437 {
568fa3fa 438 num_supplies = -1;
68b10830
MS
439 charset = -1;
440 }
568fa3fa
MS
441 }
442 else
68b10830 443 {
568fa3fa 444 num_supplies = -1;
68b10830
MS
445 charset = -1;
446 }
568fa3fa
MS
447 }
448
449 cupsFileClose(cachefile);
450 }
451
452 /*
453 * If the cache information isn't correct, scan for supplies...
454 */
455
68b10830
MS
456 if (charset < 0)
457 {
458 /*
459 * Get the configured character set...
460 */
461
462 int oid[CUPS_SNMP_MAX_OID]; /* OID for character set */
463
464
465 if (!_cupsSNMPWrite(snmp_fd, &current_addr, CUPS_SNMP_VERSION_1,
466 _cupsSNMPDefaultCommunity(), CUPS_ASN1_GET_REQUEST, 1,
467 prtGeneralCurrentLocalization))
468 return;
469
470 if (!_cupsSNMPRead(snmp_fd, &packet, CUPS_SUPPLY_TIMEOUT) ||
471 packet.object_type != CUPS_ASN1_INTEGER)
472 {
473 fprintf(stderr,
474 "DEBUG: prtGeneralCurrentLocalization type is %x, expected %x!\n",
475 packet.object_type, CUPS_ASN1_INTEGER);
476 return;
477 }
478
479 fprintf(stderr, "DEBUG2: prtGeneralCurrentLocalization=%d\n",
480 packet.object_value.integer);
481
482 _cupsSNMPCopyOID(oid, prtLocalizationCharacterSet, CUPS_SNMP_MAX_OID);
483 oid[prtLocalizationCharacterSetOffset - 2] = packet.object_value.integer;
484
485
486 if (!_cupsSNMPWrite(snmp_fd, &current_addr, CUPS_SNMP_VERSION_1,
487 _cupsSNMPDefaultCommunity(), CUPS_ASN1_GET_REQUEST, 1,
488 oid))
489 return;
490
491 if (!_cupsSNMPRead(snmp_fd, &packet, CUPS_SUPPLY_TIMEOUT) ||
492 packet.object_type != CUPS_ASN1_INTEGER)
493 {
494 fprintf(stderr,
495 "DEBUG: prtLocalizationCharacterSet type is %x, expected %x!\n",
496 packet.object_type, CUPS_ASN1_INTEGER);
497 return;
498 }
499
500 fprintf(stderr, "DEBUG2: prtLocalizationCharacterSet=%d\n",
501 packet.object_value.integer);
502 charset = packet.object_value.integer;
503 }
504
568fa3fa
MS
505 if (num_supplies < 0)
506 {
507 /*
508 * Walk the printer configuration information...
509 */
510
7a14d768 511 _cupsSNMPWalk(snmp_fd, &current_addr, CUPS_SNMP_VERSION_1,
68b10830
MS
512 _cupsSNMPDefaultCommunity(), prtMarkerSuppliesEntry,
513 CUPS_SUPPLY_TIMEOUT, backend_walk_cb, NULL);
568fa3fa
MS
514 }
515
516 /*
517 * Save the cached information...
518 */
519
520 if (num_supplies < 0)
521 num_supplies = 0;
522
523 if ((cachefile = cupsFileOpen(cachefilename, "w")) != NULL)
524 {
68b10830 525 cupsFilePrintf(cachefile, "2 %d %d\n", num_supplies, charset);
568fa3fa
MS
526 cupsFilePrintf(cachefile, "%s\n", description);
527
528 if (num_supplies > 0)
529 cupsFileWrite(cachefile, (char *)supplies,
530 num_supplies * sizeof(backend_supplies_t));
531
532 cupsFileClose(cachefile);
533 }
534
535 if (num_supplies <= 0)
536 return;
537
538 /*
539 * Get the colors...
540 */
541
542 for (i = 0; i < num_supplies; i ++)
543 strcpy(supplies[i].color, "none");
544
7a14d768 545 _cupsSNMPWalk(snmp_fd, &current_addr, CUPS_SNMP_VERSION_1,
68b10830
MS
546 _cupsSNMPDefaultCommunity(), prtMarkerColorantValue,
547 CUPS_SUPPLY_TIMEOUT, backend_walk_cb, NULL);
568fa3fa
MS
548
549 /*
550 * Output the marker-colors attribute...
551 */
552
553 for (i = 0, ptr = value; i < num_supplies; i ++, ptr += strlen(ptr))
554 {
555 if (i)
556 *ptr++ = ',';
557
558 strcpy(ptr, supplies[i].color);
559 }
560
561 fprintf(stderr, "ATTR: marker-colors=%s\n", value);
562
563 /*
564 * Output the marker-names attribute...
565 */
566
567 for (i = 0, ptr = value; i < num_supplies; i ++)
568 {
569 if (i)
570 *ptr++ = ',';
571
572 *ptr++ = '\"';
573 for (name_ptr = supplies[i].name; *name_ptr;)
574 {
575 if (*name_ptr == '\\' || *name_ptr == '\"')
576 *ptr++ = '\\';
577
578 *ptr++ = *name_ptr++;
579 }
580 *ptr++ = '\"';
581 }
582
583 *ptr = '\0';
584
585 fprintf(stderr, "ATTR: marker-names=%s\n", value);
586
587 /*
588 * Output the marker-types attribute...
589 */
590
591 for (i = 0, ptr = value; i < num_supplies; i ++, ptr += strlen(ptr))
592 {
593 if (i)
594 *ptr++ = ',';
595
596 type = supplies[i].type;
597
598 if (type < CUPS_TC_other || type > CUPS_TC_covers)
599 strcpy(ptr, "unknown");
600 else
601 strcpy(ptr, types[type - CUPS_TC_other]);
602 }
603
604 fprintf(stderr, "ATTR: marker-types=%s\n", value);
605}
606
607
608/*
68b10830 609 * 'backend_walk_cb()' - Interpret the supply value responses.
568fa3fa
MS
610 */
611
612static void
613backend_walk_cb(cups_snmp_t *packet, /* I - SNMP packet */
614 void *data) /* I - User data (unused) */
615{
616 int i, j, k; /* Looping vars */
617 static const char * const colors[8][2] =
618 { /* Standard color names */
619 { "black", "#000000" },
620 { "blue", "#0000FF" },
621 { "cyan", "#00FFFF" },
622 { "green", "#00FF00" },
623 { "magenta", "#FF00FF" },
624 { "red", "#FF0000" },
625 { "white", "#FFFFFF" },
626 { "yellow", "#FFFF00" }
627 };
628
629
630 (void)data;
631
7a14d768 632 if (_cupsSNMPIsOIDPrefixed(packet, prtMarkerColorantValue) &&
568fa3fa
MS
633 packet->object_type == CUPS_ASN1_OCTET_STRING)
634 {
635 /*
636 * Get colorant...
637 */
638
639 i = packet->object_name[prtMarkerColorantValueOffset];
640
641 fprintf(stderr, "DEBUG2: prtMarkerColorantValue.1.%d = \"%s\"\n", i,
d1c13e16 642 (char *)packet->object_value.string.bytes);
568fa3fa
MS
643
644 for (j = 0; j < num_supplies; j ++)
645 if (supplies[j].colorant == i)
646 {
647 for (k = 0; k < (int)(sizeof(colors) / sizeof(colors[0])); k ++)
d1c13e16 648 if (!strcmp(colors[k][0], (char *)packet->object_value.string.bytes))
568fa3fa
MS
649 {
650 strcpy(supplies[j].color, colors[k][1]);
651 break;
652 }
653 }
654 }
7a14d768 655 else if (_cupsSNMPIsOIDPrefixed(packet, prtMarkerSuppliesColorantIndex))
568fa3fa
MS
656 {
657 /*
658 * Get colorant index...
659 */
660
661 i = packet->object_name[prtMarkerSuppliesColorantIndexOffset];
662 if (i < 1 || i > CUPS_MAX_SUPPLIES ||
663 packet->object_type != CUPS_ASN1_INTEGER)
664 return;
665
666 fprintf(stderr, "DEBUG2: prtMarkerSuppliesColorantIndex.1.%d = %d\n", i,
667 packet->object_value.integer);
668
669 if (i > num_supplies)
670 num_supplies = i;
671
672 supplies[i - 1].colorant = packet->object_value.integer;
673 }
7a14d768 674 else if (_cupsSNMPIsOIDPrefixed(packet, prtMarkerSuppliesDescription))
568fa3fa
MS
675 {
676 /*
677 * Get supply name/description...
678 */
679
680 i = packet->object_name[prtMarkerSuppliesDescriptionOffset];
681 if (i < 1 || i > CUPS_MAX_SUPPLIES ||
682 packet->object_type != CUPS_ASN1_OCTET_STRING)
683 return;
684
568fa3fa
MS
685 if (i > num_supplies)
686 num_supplies = i;
687
68b10830
MS
688 switch (charset)
689 {
690 case CUPS_TC_csASCII :
691 case CUPS_TC_csUTF8 :
692 case CUPS_TC_csUnicodeASCII :
693 strlcpy(supplies[i - 1].name,
694 (char *)packet->object_value.string.bytes,
695 sizeof(supplies[0].name));
696 break;
697
698 case CUPS_TC_csISOLatin1 :
699 case CUPS_TC_csUnicodeLatin1 :
700 cupsCharsetToUTF8((cups_utf8_t *)supplies[i - 1].name,
701 (char *)packet->object_value.string.bytes,
702 sizeof(supplies[0].name), CUPS_ISO8859_1);
703 break;
704
705 case CUPS_TC_csShiftJIS :
706 cupsCharsetToUTF8((cups_utf8_t *)supplies[i - 1].name,
707 (char *)packet->object_value.string.bytes,
708 sizeof(supplies[0].name), CUPS_JIS_X0213);
709 break;
710
711 case CUPS_TC_csUCS4 :
712 case CUPS_TC_csUTF32 :
713 case CUPS_TC_csUTF32BE :
714 case CUPS_TC_csUTF32LE :
715 cupsUTF32ToUTF8((cups_utf8_t *)supplies[i - 1].name,
716 (cups_utf32_t *)packet->object_value.string.bytes,
717 sizeof(supplies[0].name));
718 break;
719
720 case CUPS_TC_csUnicode :
721 case CUPS_TC_csUTF16BE :
722 case CUPS_TC_csUTF16LE :
723 utf16_to_utf8((cups_utf8_t *)supplies[i - 1].name,
724 packet->object_value.string.bytes,
725 packet->object_value.string.num_bytes,
726 sizeof(supplies[0].name), charset == CUPS_TC_csUTF16LE);
727 break;
728
729 default :
730 /*
731 * If we get here, the printer is using an unknown character set and
732 * we just want to copy characters that look like ASCII...
733 */
734
735 {
736 char *src, *dst; /* Pointers into strings */
737
738
739 /*
740 * Loop safe because both the object_value and supplies char arrays
741 * are CUPS_SNMP_MAX_STRING elements long.
742 */
743
744 for (src = (char *)packet->object_value.string.bytes,
745 dst = supplies[i - 1].name;
746 *src;
747 src ++)
748 {
749 if ((*src & 0x80) || *src < ' ' || *src == 0x7f)
750 *dst++ = '?';
751 else
752 *dst++ = *src;
753 }
754
755 *dst = '\0';
756 }
757 break;
758 }
759
760 fprintf(stderr, "DEBUG2: prtMarkerSuppliesDescription.1.%d = \"%s\"\n", i,
761 supplies[i - 1].name);
762
568fa3fa 763 }
7a14d768 764 else if (_cupsSNMPIsOIDPrefixed(packet, prtMarkerSuppliesLevel))
568fa3fa
MS
765 {
766 /*
767 * Get level...
768 */
769
770 i = packet->object_name[prtMarkerSuppliesLevelOffset];
771 if (i < 1 || i > CUPS_MAX_SUPPLIES ||
772 packet->object_type != CUPS_ASN1_INTEGER)
773 return;
774
775 fprintf(stderr, "DEBUG2: prtMarkerSuppliesLevel.1.%d = %d\n", i,
776 packet->object_value.integer);
777
778 if (i > num_supplies)
779 num_supplies = i;
780
781 supplies[i - 1].level = packet->object_value.integer;
782 }
7a14d768 783 else if (_cupsSNMPIsOIDPrefixed(packet, prtMarkerSuppliesMaxCapacity))
568fa3fa
MS
784 {
785 /*
786 * Get max capacity...
787 */
788
789 i = packet->object_name[prtMarkerSuppliesMaxCapacityOffset];
790 if (i < 1 || i > CUPS_MAX_SUPPLIES ||
791 packet->object_type != CUPS_ASN1_INTEGER)
792 return;
793
794 fprintf(stderr, "DEBUG2: prtMarkerSuppliesMaxCapacity.1.%d = %d\n", i,
795 packet->object_value.integer);
796
797 if (i > num_supplies)
798 num_supplies = i;
799
800 supplies[i - 1].max_capacity = packet->object_value.integer;
801 }
7a14d768 802 else if (_cupsSNMPIsOIDPrefixed(packet, prtMarkerSuppliesType))
568fa3fa
MS
803 {
804 /*
805 * Get marker type...
806 */
807
808 i = packet->object_name[prtMarkerSuppliesTypeOffset];
809 if (i < 1 || i > CUPS_MAX_SUPPLIES ||
810 packet->object_type != CUPS_ASN1_INTEGER)
811 return;
812
813 fprintf(stderr, "DEBUG2: prtMarkerSuppliesType.1.%d = %d\n", i,
814 packet->object_value.integer);
815
816 if (i > num_supplies)
817 num_supplies = i;
818
819 supplies[i - 1].type = packet->object_value.integer;
820 }
821}
822
823
68b10830
MS
824/*
825 * 'utf16_to_utf8()' - Convert UTF-16 text to UTF-8.
826 */
827
828static void
829utf16_to_utf8(
830 cups_utf8_t *dst, /* I - Destination buffer */
831 const unsigned char *src, /* I - Source string */
832 size_t srcsize, /* I - Size of source string */
833 size_t dstsize, /* I - Size of destination buffer */
834 int le) /* I - Source is little-endian? */
835{
836 cups_utf32_t ch, /* Current character */
837 temp[CUPS_SNMP_MAX_STRING],
838 /* UTF-32 string */
839 *ptr; /* Pointer into UTF-32 string */
840
841
842 for (ptr = temp; srcsize >= 2;)
843 {
844 if (le)
845 ch = src[0] | (src[1] << 8);
846 else
847 ch = (src[0] << 8) | src[1];
848
849 src += 2;
850 srcsize -= 2;
851
852 if (ch >= 0xd800 && ch <= 0xdbff && srcsize >= 2)
853 {
854 /*
855 * Multi-word UTF-16 char...
856 */
857
858 int lch; /* Lower word */
859
860
861 if (le)
862 lch = src[0] | (src[1] << 8);
863 else
864 lch = (src[0] << 8) | src[1];
865
866 if (lch >= 0xdc00 && lch <= 0xdfff)
867 {
868 src += 2;
869 srcsize -= 2;
870
871 ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000;
872 }
873 }
874
875 if (ptr < (temp + CUPS_SNMP_MAX_STRING - 1))
876 *ptr++ = ch;
877 }
878
879 *ptr = '\0';
880
881 cupsUTF32ToUTF8(dst, temp, dstsize);
882}
883
884
568fa3fa
MS
885/*
886 * End of "$Id$".
887 */