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