]>
Commit | Line | Data |
---|---|---|
ef416fc2 | 1 | /* |
f7faf1f5 | 2 | * "$Id: mailto.c 5235 2006-03-06 13:02:23Z mike $" |
ef416fc2 | 3 | * |
4 | * "mailto" notifier for the Common UNIX Printing System (CUPS). | |
5 | * | |
6 | * Copyright 1997-2005 by Easy Software Products. | |
7 | * | |
8 | * These coded instructions, statements, and computer programs are the | |
9 | * property of Easy Software Products and are protected by Federal | |
10 | * copyright law. Distribution and use rights are outlined in the file | |
11 | * "LICENSE.txt" which should have been included with this file. If this | |
12 | * file is missing or damaged please contact Easy Software Products | |
13 | * at: | |
14 | * | |
15 | * Attn: CUPS Licensing Information | |
16 | * Easy Software Products | |
17 | * 44141 Airport View Drive, Suite 204 | |
18 | * Hollywood, Maryland 20636 USA | |
19 | * | |
20 | * Voice: (301) 373-9600 | |
21 | * EMail: cups-info@cups.org | |
22 | * WWW: http://www.cups.org | |
23 | * | |
24 | * Contents: | |
25 | * | |
fa73b229 | 26 | * main() - Main entry for the mailto notifier. |
27 | * email_message() - Email a notification message. | |
28 | * load_configuration() - Load the mailto.conf file. | |
29 | * pipe_sendmail() - Open a pipe to sendmail... | |
30 | * print_attributes() - Print the attributes in a request... | |
ef416fc2 | 31 | */ |
32 | ||
33 | /* | |
34 | * Include necessary headers... | |
35 | */ | |
36 | ||
37 | #include <cups/cups.h> | |
fa73b229 | 38 | #include <cups/i18n.h> |
ef416fc2 | 39 | #include <cups/string.h> |
fa73b229 | 40 | #include <errno.h> |
41 | #include <sys/wait.h> | |
42 | #include <signal.h> | |
43 | ||
44 | ||
45 | /* | |
46 | * Globals... | |
47 | */ | |
48 | ||
49 | char mailtoCc[1024]; /* Cc email address */ | |
50 | char mailtoFrom[1024]; /* From email address */ | |
51 | char mailtoReplyTo[1024]; /* Reply-To email address */ | |
52 | char mailtoSubject[1024]; /* Subject prefix */ | |
53 | char mailtoSMTPServer[1024]; /* SMTP server to use */ | |
54 | char mailtoSendmail[1024]; /* Sendmail program to use */ | |
55 | ||
56 | ||
57 | /* | |
58 | * Local functions... | |
59 | */ | |
60 | ||
61 | void email_message(const char *to, const char *subject, | |
62 | const char *text); | |
63 | int load_configuration(void); | |
64 | cups_file_t *pipe_sendmail(const char *to); | |
65 | void print_attributes(ipp_t *ipp, int indent); | |
ef416fc2 | 66 | |
67 | ||
68 | /* | |
69 | * 'main()' - Main entry for the mailto notifier. | |
70 | */ | |
71 | ||
72 | int /* O - Exit status */ | |
73 | main(int argc, /* I - Number of command-line arguments */ | |
74 | char *argv[]) /* I - Command-line arguments */ | |
75 | { | |
fa73b229 | 76 | int i; /* Looping var */ |
77 | ipp_t *msg; /* Event message from scheduler */ | |
78 | ipp_state_t state; /* IPP event state */ | |
79 | char *subject, /* Subject for notification message */ | |
80 | *text; /* Text for notification message */ | |
81 | cups_lang_t *lang; /* Language info */ | |
82 | char temp[1024]; /* Temporary string */ | |
83 | int templen; /* Length of temporary string */ | |
84 | #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) | |
85 | struct sigaction action; /* POSIX sigaction data */ | |
86 | #endif /* HAVE_SIGACTION && !HAVE_SIGSET */ | |
87 | ||
88 | ||
89 | /* | |
90 | * Don't buffer stderr... | |
91 | */ | |
92 | ||
93 | setbuf(stderr, NULL); | |
94 | ||
95 | /* | |
96 | * Ignore SIGPIPE signals... | |
97 | */ | |
98 | ||
99 | #ifdef HAVE_SIGSET | |
100 | sigset(SIGPIPE, SIG_IGN); | |
101 | #elif defined(HAVE_SIGACTION) | |
102 | memset(&action, 0, sizeof(action)); | |
103 | action.sa_handler = SIG_IGN; | |
104 | sigaction(SIGPIPE, &action, NULL); | |
105 | #else | |
106 | signal(SIGPIPE, SIG_IGN); | |
107 | #endif /* HAVE_SIGSET */ | |
108 | ||
109 | /* | |
110 | * Validate command-line options... | |
111 | */ | |
112 | ||
113 | if (argc != 3) | |
114 | { | |
115 | fputs("Usage: mailto mailto:user@domain.com notify-user-data\n", stderr); | |
116 | return (1); | |
117 | } | |
118 | ||
119 | if (strncmp(argv[1], "mailto:", 7)) | |
120 | { | |
121 | fprintf(stderr, "ERROR: Bad recipient \"%s\"!\n", argv[1]); | |
122 | return (1); | |
123 | } | |
124 | ||
125 | fprintf(stderr, "DEBUG: argc=%d\n", argc); | |
126 | for (i = 0; i < argc; i ++) | |
127 | fprintf(stderr, "DEBUG: argv[%d]=\"%s\"\n", i, argv[i]); | |
128 | ||
129 | /* | |
130 | * Load configuration data... | |
131 | */ | |
132 | ||
133 | if ((lang = cupsLangDefault()) == NULL) | |
134 | return (1); | |
135 | ||
136 | if (!load_configuration()) | |
137 | return (1); | |
138 | ||
139 | /* | |
140 | * Get the reply-to address... | |
141 | */ | |
142 | ||
143 | templen = sizeof(temp); | |
144 | httpDecode64_2(temp, &templen, argv[2]); | |
145 | ||
146 | if (!strncmp(temp, "mailto:", 7)) | |
147 | strlcpy(mailtoReplyTo, temp + 7, sizeof(mailtoReplyTo)); | |
148 | else if (temp[0]) | |
149 | fprintf(stderr, "WARNING: Bad notify-user-data value (%d bytes) ignored!\n", | |
150 | templen); | |
151 | ||
152 | /* | |
153 | * Loop forever until we run out of events... | |
154 | */ | |
155 | ||
156 | for (;;) | |
157 | { | |
158 | /* | |
159 | * Get the next event... | |
160 | */ | |
161 | ||
162 | msg = ippNew(); | |
163 | while ((state = ippReadFile(0, msg)) != IPP_DATA) | |
164 | { | |
165 | if (state <= IPP_IDLE) | |
166 | break; | |
167 | } | |
168 | ||
169 | fprintf(stderr, "DEBUG: state=%d\n", state); | |
170 | ||
171 | if (state == IPP_ERROR) | |
172 | fputs("DEBUG: ippReadFile() returned IPP_ERROR!\n", stderr); | |
173 | ||
174 | if (state <= IPP_IDLE) | |
175 | { | |
176 | /* | |
177 | * Out of messages, free memory and then exit... | |
178 | */ | |
179 | ||
180 | ippDelete(msg); | |
181 | return (0); | |
182 | } | |
183 | ||
184 | /* | |
185 | * Get the subject and text for the message, then email it... | |
186 | */ | |
187 | ||
188 | subject = cupsNotifySubject(lang, msg); | |
189 | text = cupsNotifyText(lang, msg); | |
190 | ||
191 | fprintf(stderr, "DEBUG: subject=\"%s\"\n", subject); | |
192 | fprintf(stderr, "DEBUG: text=\"%s\"\n", text); | |
193 | ||
194 | if (subject && text) | |
195 | email_message(argv[1] + 7, subject, text); | |
196 | else | |
197 | { | |
198 | fputs("ERROR: Missing attributes in event notification!\n", stderr); | |
199 | print_attributes(msg, 4); | |
200 | } | |
201 | ||
202 | /* | |
203 | * Free the memory used for this event... | |
204 | */ | |
205 | ||
206 | if (subject) | |
207 | free(subject); | |
208 | ||
209 | if (text) | |
210 | free(text); | |
211 | ||
212 | ippDelete(msg); | |
213 | } | |
214 | } | |
215 | ||
216 | ||
217 | /* | |
218 | * 'email_message()' - Email a notification message. | |
219 | */ | |
220 | ||
221 | void | |
222 | email_message(const char *to, /* I - Recipient of message */ | |
223 | const char *subject, /* I - Subject of message */ | |
224 | const char *text) /* I - Text of message */ | |
225 | { | |
226 | cups_file_t *fp; /* Pipe/socket to mail server */ | |
227 | const char *nl; /* Newline to use */ | |
228 | char response[1024]; /* SMTP response buffer */ | |
229 | ||
230 | ||
231 | /* | |
232 | * Connect to the mail server... | |
233 | */ | |
234 | ||
235 | if (mailtoSendmail[0]) | |
236 | { | |
237 | /* | |
238 | * Use the sendmail command... | |
239 | */ | |
240 | ||
241 | fp = pipe_sendmail(to); | |
242 | ||
243 | if (!fp) | |
244 | return; | |
245 | ||
246 | nl = "\n"; | |
247 | } | |
248 | else | |
249 | { | |
250 | /* | |
251 | * Use an SMTP server... | |
252 | */ | |
253 | ||
254 | char hostbuf[1024]; /* Local hostname */ | |
255 | ||
256 | ||
257 | if (strchr(mailtoSMTPServer, ':')) | |
258 | fp = cupsFileOpen(mailtoSMTPServer, "s"); | |
259 | else | |
260 | { | |
261 | char spec[1024]; /* Host:service spec */ | |
262 | ||
263 | ||
264 | snprintf(spec, sizeof(spec), "%s:smtp", mailtoSMTPServer); | |
265 | fp = cupsFileOpen(spec, "s"); | |
266 | } | |
267 | ||
268 | if (!fp) | |
269 | { | |
270 | fprintf(stderr, "ERROR: Unable to connect to SMTP server \"%s\"!\n", | |
271 | mailtoSMTPServer); | |
272 | return; | |
273 | } | |
274 | ||
275 | fprintf(stderr, "DEBUG: Connected to \"%s\"...\n", mailtoSMTPServer); | |
276 | ||
757d2cad | 277 | cupsFilePrintf(fp, "HELO %s\r\n", |
278 | httpGetHostname(NULL, hostbuf, sizeof(hostbuf))); | |
fa73b229 | 279 | fprintf(stderr, "DEBUG: >>> HELO %s\n", hostbuf); |
280 | ||
281 | if (!cupsFileGets(fp, response, sizeof(response)) || atoi(response) >= 500) | |
282 | goto smtp_error; | |
283 | fprintf(stderr, "DEBUG: <<< %s\n", response); | |
284 | ||
285 | cupsFilePrintf(fp, "MAIL FROM:%s\r\n", mailtoFrom); | |
286 | fprintf(stderr, "DEBUG: >>> MAIL FROM:%s\n", mailtoFrom); | |
287 | ||
288 | if (!cupsFileGets(fp, response, sizeof(response)) || atoi(response) >= 500) | |
289 | goto smtp_error; | |
290 | fprintf(stderr, "DEBUG: <<< %s\n", response); | |
291 | ||
292 | cupsFilePrintf(fp, "RCPT TO:%s\r\n", to); | |
293 | fprintf(stderr, "DEBUG: >>> RCPT TO:%s\n", to); | |
294 | ||
295 | if (!cupsFileGets(fp, response, sizeof(response)) || atoi(response) >= 500) | |
296 | goto smtp_error; | |
297 | fprintf(stderr, "DEBUG: <<< %s\n", response); | |
298 | ||
299 | cupsFilePuts(fp, "DATA\r\n"); | |
300 | fputs("DEBUG: DATA\n", stderr); | |
301 | ||
302 | if (!cupsFileGets(fp, response, sizeof(response)) || atoi(response) >= 500) | |
303 | goto smtp_error; | |
304 | fprintf(stderr, "DEBUG: <<< %s\n", response); | |
305 | ||
306 | nl = "\r\n"; | |
307 | } | |
308 | ||
309 | /* | |
310 | * Send the message... | |
311 | */ | |
312 | ||
313 | cupsFilePrintf(fp, "Date: %s%s", httpGetDateString(time(NULL)), nl); | |
314 | cupsFilePrintf(fp, "From: %s%s", mailtoFrom, nl); | |
315 | cupsFilePrintf(fp, "Subject: %s %s%s", mailtoSubject, subject, nl); | |
316 | if (mailtoReplyTo[0]) | |
317 | { | |
318 | cupsFilePrintf(fp, "Sender: %s%s", mailtoReplyTo, nl); | |
319 | cupsFilePrintf(fp, "Reply-To: %s%s", mailtoReplyTo, nl); | |
320 | } | |
321 | cupsFilePrintf(fp, "To: %s%s", to, nl); | |
322 | if (mailtoCc[0]) | |
323 | cupsFilePrintf(fp, "Cc: %s%s", mailtoCc, nl); | |
324 | cupsFilePrintf(fp, "Content-Type: text/plain%s", nl); | |
325 | cupsFilePuts(fp, nl); | |
326 | cupsFilePrintf(fp, "%s%s", text, nl); | |
327 | cupsFilePrintf(fp, ".\n", nl); | |
328 | ||
329 | /* | |
330 | * Close the connection to the mail server... | |
331 | */ | |
332 | ||
333 | if (mailtoSendmail[0]) | |
334 | { | |
335 | /* | |
336 | * Close the pipe and wait for the sendmail command to finish... | |
337 | */ | |
338 | ||
339 | int status; /* Exit status */ | |
340 | ||
341 | ||
342 | cupsFileClose(fp); | |
343 | ||
344 | if (wait(&status)) | |
345 | status = errno << 8; | |
346 | ||
347 | /* | |
348 | * Report any non-zero status... | |
349 | */ | |
350 | ||
351 | if (status) | |
352 | { | |
353 | if (WIFEXITED(status)) | |
354 | fprintf(stderr, "ERROR: Sendmail command returned status %d!\n", | |
355 | WEXITSTATUS(status)); | |
356 | else | |
357 | fprintf(stderr, "ERROR: Sendmail command crashed on signal %d!\n", | |
358 | WTERMSIG(status)); | |
359 | } | |
360 | } | |
361 | else | |
362 | { | |
363 | /* | |
364 | * Finish up the SMTP submission and close the connection... | |
365 | */ | |
366 | ||
367 | if (!cupsFileGets(fp, response, sizeof(response)) || atoi(response) >= 500) | |
368 | goto smtp_error; | |
369 | fprintf(stderr, "DEBUG: <<< %s\n", response); | |
370 | ||
371 | /* | |
372 | * Process SMTP errors here... | |
373 | */ | |
374 | ||
375 | smtp_error: | |
376 | ||
377 | cupsFilePuts(fp, "QUIT\r\n"); | |
378 | fputs("DEBUG: QUIT\n", stderr); | |
379 | ||
380 | if (!cupsFileGets(fp, response, sizeof(response)) || atoi(response) >= 500) | |
381 | goto smtp_error; | |
382 | fprintf(stderr, "DEBUG: <<< %s\n", response); | |
383 | ||
384 | cupsFileClose(fp); | |
385 | ||
386 | fprintf(stderr, "DEBUG: Closed connection to \"%s\"...\n", | |
387 | mailtoSMTPServer); | |
388 | } | |
389 | } | |
390 | ||
391 | ||
392 | /* | |
393 | * 'load_configuration()' - Load the mailto.conf file. | |
394 | */ | |
395 | ||
396 | int /* I - 1 on success, 0 on failure */ | |
397 | load_configuration(void) | |
398 | { | |
399 | cups_file_t *fp; /* mailto.conf file */ | |
400 | const char *server_root, /* CUPS_SERVERROOT environment variable */ | |
401 | *server_admin; /* SERVER_ADMIN environment variable */ | |
402 | char line[1024], /* Line from file */ | |
403 | *value; /* Value for directive */ | |
404 | int linenum; /* Line number in file */ | |
405 | ||
406 | ||
407 | /* | |
408 | * Initialize defaults... | |
409 | */ | |
410 | ||
411 | mailtoCc[0] = '\0'; | |
412 | ||
413 | if ((server_admin = getenv("SERVER_ADMIN")) != NULL) | |
414 | strlcpy(mailtoFrom, server_admin, sizeof(mailtoFrom)); | |
415 | else | |
416 | snprintf(mailtoFrom, sizeof(mailtoFrom), "root@%s", | |
757d2cad | 417 | httpGetHostname(NULL, line, sizeof(line))); |
fa73b229 | 418 | |
419 | strlcpy(mailtoSendmail, "/usr/sbin/sendmail", sizeof(mailtoSendmail)); | |
420 | ||
421 | mailtoSMTPServer[0] = '\0'; | |
422 | ||
423 | mailtoSubject[0] = '\0'; | |
424 | ||
425 | /* | |
426 | * Try loading the config file... | |
427 | */ | |
428 | ||
429 | if ((server_root = getenv("CUPS_SERVERROOT")) == NULL) | |
430 | server_root = CUPS_SERVERROOT; | |
431 | ||
432 | snprintf(line, sizeof(line), "%s/mailto.conf", server_root); | |
433 | ||
434 | if ((fp = cupsFileOpen(line, "r")) == NULL) | |
435 | { | |
436 | fprintf(stderr, "ERROR: Unable to open \"%s\" - %s\n", line, | |
437 | strerror(errno)); | |
438 | return (1); | |
439 | } | |
440 | ||
441 | linenum = 0; | |
442 | ||
443 | while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum)) | |
444 | { | |
445 | if (!value) | |
446 | { | |
447 | fprintf(stderr, "ERROR: No value found for %s directive on line %d!\n", | |
448 | line, linenum); | |
449 | cupsFileClose(fp); | |
450 | return (0); | |
451 | } | |
452 | ||
453 | if (!strcasecmp(line, "Cc")) | |
454 | strlcpy(mailtoCc, value, sizeof(mailtoCc)); | |
455 | else if (!strcasecmp(line, "From")) | |
456 | strlcpy(mailtoFrom, value, sizeof(mailtoFrom)); | |
457 | else if (!strcasecmp(line, "Sendmail")) | |
458 | { | |
459 | strlcpy(mailtoSendmail, value, sizeof(mailtoSendmail)); | |
460 | mailtoSMTPServer[0] = '\0'; | |
461 | } | |
462 | else if (!strcasecmp(line, "SMTPServer")) | |
463 | { | |
464 | mailtoSendmail[0] = '\0'; | |
465 | strlcpy(mailtoSMTPServer, value, sizeof(mailtoSMTPServer)); | |
466 | } | |
467 | else if (!strcasecmp(line, "Subject")) | |
468 | strlcpy(mailtoSubject, value, sizeof(mailtoSubject)); | |
469 | else | |
470 | { | |
471 | fprintf(stderr, | |
472 | "ERROR: Unknown configuration directive \"%s\" on line %d!\n", | |
473 | line, linenum); | |
474 | } | |
475 | } | |
476 | ||
477 | /* | |
478 | * Close file and return... | |
479 | */ | |
480 | ||
481 | cupsFileClose(fp); | |
482 | ||
483 | return (1); | |
484 | } | |
485 | ||
486 | ||
487 | /* | |
488 | * 'pipe_sendmail()' - Open a pipe to sendmail... | |
489 | */ | |
490 | ||
491 | cups_file_t * /* O - CUPS file */ | |
492 | pipe_sendmail(const char *to) /* I - To: address */ | |
493 | { | |
494 | cups_file_t *fp; /* CUPS file */ | |
495 | int pid; /* Process ID */ | |
496 | int pipefds[2]; /* Pipe file descriptors */ | |
497 | int argc; /* Number of arguments */ | |
498 | char *argv[100], /* Argument array */ | |
499 | line[1024], /* Sendmail command + args */ | |
500 | *lineptr; /* Pointer into line */ | |
501 | ||
502 | ||
503 | /* | |
504 | * First break the mailtoSendmail string into arguments... | |
505 | */ | |
506 | ||
507 | strlcpy(line, mailtoSendmail, sizeof(line)); | |
508 | argv[0] = line; | |
509 | argc = 1; | |
510 | ||
511 | for (lineptr = strchr(line, ' '); lineptr; lineptr = strchr(lineptr, ' ')) | |
512 | { | |
513 | while (*lineptr == ' ') | |
514 | *lineptr++ = '\0'; | |
515 | ||
516 | if (*lineptr) | |
517 | { | |
518 | /* | |
519 | * Point to the next argument... | |
520 | */ | |
521 | ||
522 | argv[argc ++] = lineptr; | |
523 | ||
524 | /* | |
525 | * Stop if we have too many... | |
526 | */ | |
527 | ||
528 | if (argc >= (int)(sizeof(argv) / sizeof(argv[0]) - 2)) | |
529 | break; | |
530 | } | |
531 | } | |
532 | ||
533 | argv[argc ++] = (char *)to; | |
534 | argv[argc] = NULL; | |
535 | ||
536 | /* | |
537 | * Create the pipe... | |
538 | */ | |
539 | ||
540 | if (pipe(pipefds)) | |
541 | { | |
542 | perror("ERROR: Unable to create pipe"); | |
543 | return (NULL); | |
544 | } | |
545 | ||
546 | /* | |
547 | * Then run the command... | |
548 | */ | |
549 | ||
550 | if ((pid = fork()) == 0) | |
551 | { | |
552 | /* | |
553 | * Child goes here - redirect stdin to the input side of the pipe, | |
554 | * redirect stdout to stderr, and exec... | |
555 | */ | |
556 | ||
557 | close(0); | |
558 | dup(pipefds[0]); | |
559 | ||
560 | close(1); | |
561 | dup(2); | |
562 | ||
563 | close(pipefds[0]); | |
564 | close(pipefds[1]); | |
565 | ||
566 | execvp(argv[0], argv); | |
567 | exit(errno); | |
568 | } | |
569 | else if (pid < 0) | |
570 | { | |
571 | /* | |
572 | * Unable to fork - error out... | |
573 | */ | |
574 | ||
575 | perror("ERROR: Unable to fork command"); | |
576 | ||
577 | close(pipefds[0]); | |
578 | close(pipefds[1]); | |
579 | ||
580 | return (NULL); | |
581 | } | |
582 | ||
583 | /* | |
584 | * Create a CUPS file using the output side of the pipe and close the | |
585 | * input side... | |
586 | */ | |
587 | ||
588 | close(pipefds[0]); | |
589 | ||
590 | if ((fp = cupsFileOpenFd(pipefds[1], "w")) == NULL) | |
591 | { | |
592 | int status; /* Status of command */ | |
593 | ||
594 | ||
595 | close(pipefds[1]); | |
596 | wait(&status); | |
597 | } | |
598 | ||
599 | return (fp); | |
600 | } | |
601 | ||
602 | ||
603 | /* | |
604 | * 'print_attributes()' - Print the attributes in a request... | |
605 | */ | |
606 | ||
607 | void | |
608 | print_attributes(ipp_t *ipp, /* I - IPP request */ | |
609 | int indent) /* I - Indentation */ | |
610 | { | |
611 | int i; /* Looping var */ | |
612 | ipp_tag_t group; /* Current group */ | |
613 | ipp_attribute_t *attr; /* Current attribute */ | |
614 | ipp_value_t *val; /* Current value */ | |
615 | static const char * const tags[] = /* Value/group tag strings */ | |
616 | { | |
617 | "reserved-00", | |
618 | "operation-attributes-tag", | |
619 | "job-attributes-tag", | |
620 | "end-of-attributes-tag", | |
621 | "printer-attributes-tag", | |
622 | "unsupported-attributes-tag", | |
623 | "subscription-attributes-tag", | |
624 | "event-attributes-tag", | |
625 | "reserved-08", | |
626 | "reserved-09", | |
627 | "reserved-0A", | |
628 | "reserved-0B", | |
629 | "reserved-0C", | |
630 | "reserved-0D", | |
631 | "reserved-0E", | |
632 | "reserved-0F", | |
633 | "unsupported", | |
634 | "default", | |
635 | "unknown", | |
636 | "no-value", | |
637 | "reserved-14", | |
638 | "not-settable", | |
639 | "delete-attr", | |
640 | "admin-define", | |
641 | "reserved-18", | |
642 | "reserved-19", | |
643 | "reserved-1A", | |
644 | "reserved-1B", | |
645 | "reserved-1C", | |
646 | "reserved-1D", | |
647 | "reserved-1E", | |
648 | "reserved-1F", | |
649 | "reserved-20", | |
650 | "integer", | |
651 | "boolean", | |
652 | "enum", | |
653 | "reserved-24", | |
654 | "reserved-25", | |
655 | "reserved-26", | |
656 | "reserved-27", | |
657 | "reserved-28", | |
658 | "reserved-29", | |
659 | "reserved-2a", | |
660 | "reserved-2b", | |
661 | "reserved-2c", | |
662 | "reserved-2d", | |
663 | "reserved-2e", | |
664 | "reserved-2f", | |
665 | "octetString", | |
666 | "dateTime", | |
667 | "resolution", | |
668 | "rangeOfInteger", | |
669 | "begCollection", | |
670 | "textWithLanguage", | |
671 | "nameWithLanguage", | |
672 | "endCollection", | |
673 | "reserved-38", | |
674 | "reserved-39", | |
675 | "reserved-3a", | |
676 | "reserved-3b", | |
677 | "reserved-3c", | |
678 | "reserved-3d", | |
679 | "reserved-3e", | |
680 | "reserved-3f", | |
681 | "reserved-40", | |
682 | "textWithoutLanguage", | |
683 | "nameWithoutLanguage", | |
684 | "reserved-43", | |
685 | "keyword", | |
686 | "uri", | |
687 | "uriScheme", | |
688 | "charset", | |
689 | "naturalLanguage", | |
690 | "mimeMediaType", | |
691 | "memberName" | |
692 | }; | |
693 | ||
694 | ||
695 | for (group = IPP_TAG_ZERO, attr = ipp->attrs; attr; attr = attr->next) | |
696 | { | |
697 | if ((attr->group_tag == IPP_TAG_ZERO && indent <= 8) || !attr->name) | |
698 | { | |
699 | group = IPP_TAG_ZERO; | |
700 | fputc('\n', stderr); | |
701 | continue; | |
702 | } | |
703 | ||
704 | if (group != attr->group_tag) | |
705 | { | |
706 | group = attr->group_tag; | |
707 | ||
708 | fprintf(stderr, "DEBUG: %*s%s:\n\n", indent - 4, "", tags[group]); | |
709 | } | |
710 | ||
711 | fprintf(stderr, "DEBUG: %*s%s (", indent, "", attr->name); | |
712 | if (attr->num_values > 1) | |
713 | fputs("1setOf ", stderr); | |
714 | fprintf(stderr, "%s):", tags[attr->value_tag]); | |
715 | ||
716 | switch (attr->value_tag) | |
717 | { | |
718 | case IPP_TAG_ENUM : | |
719 | case IPP_TAG_INTEGER : | |
720 | for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++) | |
721 | fprintf(stderr, " %d", val->integer); | |
722 | fputc('\n', stderr); | |
723 | break; | |
724 | ||
725 | case IPP_TAG_BOOLEAN : | |
726 | for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++) | |
727 | fprintf(stderr, " %s", val->boolean ? "true" : "false"); | |
728 | fputc('\n', stderr); | |
729 | break; | |
730 | ||
731 | case IPP_TAG_RANGE : | |
732 | for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++) | |
733 | fprintf(stderr, " %d-%d", val->range.lower, val->range.upper); | |
734 | fputc('\n', stderr); | |
735 | break; | |
736 | ||
737 | case IPP_TAG_DATE : | |
738 | { | |
739 | time_t vtime; /* Date/Time value */ | |
740 | struct tm *vdate; /* Date info */ | |
741 | char vstring[256]; /* Formatted time */ | |
742 | ||
743 | for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++) | |
744 | { | |
745 | vtime = ippDateToTime(val->date); | |
746 | vdate = localtime(&vtime); | |
747 | strftime(vstring, sizeof(vstring), "%c", vdate); | |
748 | fprintf(stderr, " (%s)", vstring); | |
749 | } | |
750 | } | |
751 | fputc('\n', stderr); | |
752 | break; | |
753 | ||
754 | case IPP_TAG_RESOLUTION : | |
755 | for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++) | |
756 | fprintf(stderr, " %dx%d%s", val->resolution.xres, | |
757 | val->resolution.yres, | |
758 | val->resolution.units == IPP_RES_PER_INCH ? "dpi" : "dpc"); | |
759 | fputc('\n', stderr); | |
760 | break; | |
761 | ||
762 | case IPP_TAG_STRING : | |
763 | case IPP_TAG_TEXTLANG : | |
764 | case IPP_TAG_NAMELANG : | |
765 | case IPP_TAG_TEXT : | |
766 | case IPP_TAG_NAME : | |
767 | case IPP_TAG_KEYWORD : | |
768 | case IPP_TAG_URI : | |
769 | case IPP_TAG_URISCHEME : | |
770 | case IPP_TAG_CHARSET : | |
771 | case IPP_TAG_LANGUAGE : | |
772 | case IPP_TAG_MIMETYPE : | |
773 | for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++) | |
774 | fprintf(stderr, " \"%s\"", val->string.text); | |
775 | fputc('\n', stderr); | |
776 | break; | |
777 | ||
778 | case IPP_TAG_BEGIN_COLLECTION : | |
779 | fputc('\n', stderr); | |
780 | ||
781 | for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++) | |
782 | { | |
783 | if (i) | |
784 | fputc('\n', stderr); | |
785 | print_attributes(val->collection, indent + 4); | |
786 | } | |
787 | break; | |
788 | ||
789 | default : | |
790 | fprintf(stderr, "UNKNOWN (%d values)\n", attr->num_values); | |
791 | break; | |
792 | } | |
793 | } | |
ef416fc2 | 794 | } |
795 | ||
796 | ||
797 | /* | |
f7faf1f5 | 798 | * End of "$Id: mailto.c 5235 2006-03-06 13:02:23Z mike $". |
ef416fc2 | 799 | */ |