]> git.ipfire.org Git - thirdparty/cups.git/blame - test/ipptest.c
Merge changes from CUPS 1.4svn-r8252.
[thirdparty/cups.git] / test / ipptest.c
CommitLineData
ef416fc2 1/*
b19ccc9e 2 * "$Id: ipptest.c 7847 2008-08-19 04:22:14Z mike $"
ef416fc2 3 *
4 * IPP test command for the Common UNIX Printing System (CUPS).
5 *
d2354e63 6 * Copyright 2007-2009 by Apple Inc.
b94498cf 7 * Copyright 1997-2007 by Easy Software Products.
ef416fc2 8 *
9 * These coded instructions, statements, and computer programs are the
bc44d920 10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
ef416fc2 14 *
15 * Contents:
16 *
e00b005a 17 * main() - Parse options and do tests.
18 * do_tests() - Do tests as specified in the test file.
e00b005a 19 * get_token() - Get a token from a file.
20 * print_attr() - Print an attribute on the screen.
21 * usage() - Show program usage.
ef416fc2 22 */
23
24/*
25 * Include necessary headers...
26 */
27
28#include <stdio.h>
29#include <stdlib.h>
30#include <cups/string.h>
31#include <errno.h>
32#include <ctype.h>
33
34#include <cups/cups.h>
35#include <cups/language.h>
36
37
e00b005a 38/*
39 * Globals...
40 */
41
89d46774 42int Verbosity = 0; /* Show all attributes? */
e00b005a 43
44
ef416fc2 45/*
46 * Local functions...
47 */
48
49int do_tests(const char *, const char *);
50ipp_op_t ippOpValue(const char *);
51ipp_status_t ippErrorValue(const char *);
ef416fc2 52char *get_token(FILE *, char *, int, int *linenum);
53void print_attr(ipp_attribute_t *);
d2354e63 54void print_col(ipp_t *col);
e00b005a 55void usage(const char *option);
ef416fc2 56
57
58/*
59 * 'main()' - Parse options and do tests.
60 */
61
62int /* O - Exit status */
63main(int argc, /* I - Number of command-line arguments */
64 char *argv[]) /* I - Command-line arguments */
65{
66 int i; /* Looping var */
67 int status; /* Status of tests... */
e00b005a 68 const char *uri; /* URI to use */
69 const char *testfile; /* Test file to use */
8ca02f3c 70 int interval; /* Test interval */
ef416fc2 71
72
73 /*
74 * We need at least:
75 *
76 * testipp URL testfile
77 */
78
e00b005a 79 uri = NULL;
80 testfile = NULL;
81 status = 0;
8ca02f3c 82 interval = 0;
e00b005a 83
84 for (i = 1; i < argc; i ++)
ef416fc2 85 {
e00b005a 86 if (argv[i][0] == '-')
87 {
88 if (!strcmp(argv[i], "-v"))
89 Verbosity ++;
b94498cf 90 else if (!strcmp(argv[i], "-d"))
91 {
92 i ++;
93
94 if (i >= argc)
95 usage(NULL);
96 else
97 putenv(argv[i]);
98 }
8ca02f3c 99 else if (!strcmp(argv[i], "-i"))
100 {
101 i++;
102
103 if (i >= argc)
104 usage(NULL);
105 else
106 interval = atoi(argv[i]);
107 }
e00b005a 108 else
109 usage(argv[i]);
110 }
111 else if (!strncmp(argv[i], "ipp://", 6) ||
112 !strncmp(argv[i], "http://", 7) ||
113 !strncmp(argv[i], "https://", 8))
114 {
115 /*
116 * Set URI...
117 */
ef416fc2 118
e00b005a 119 if (!testfile && uri)
120 usage(NULL);
121
122 uri = argv[i];
123 testfile = NULL;
124 }
125 else
126 {
127 /*
128 * Run test...
129 */
130
131 testfile = argv[i];
132
133 if (!do_tests(uri, testfile))
134 status ++;
135 }
136 }
ef416fc2 137
e00b005a 138 if (!uri || !testfile)
139 usage(NULL);
ef416fc2 140
8ca02f3c 141 /*
142 * Loop if the interval is set...
143 */
144
145 if (interval)
146 {
147 for (;;)
148 {
149 sleep(interval);
150 do_tests(uri, testfile);
151 }
152 }
153
ef416fc2 154 /*
155 * Exit...
156 */
157
e00b005a 158 return (status);
ef416fc2 159}
160
161
162/*
163 * 'do_tests()' - Do tests as specified in the test file.
164 */
165
166int /* 1 = success, 0 = failure */
167do_tests(const char *uri, /* I - URI to connect on */
168 const char *testfile) /* I - Test file to use */
169{
170 int i; /* Looping var */
171 int linenum; /* Current line number */
172 int version; /* IPP version number to use */
173 http_t *http; /* HTTP connection to server */
52f6f666 174 char scheme[HTTP_MAX_URI], /* URI scheme */
ef416fc2 175 userpass[HTTP_MAX_URI], /* username:password */
176 server[HTTP_MAX_URI], /* Server */
177 resource[HTTP_MAX_URI]; /* Resource path */
178 int port; /* Port number */
179 FILE *fp; /* Test file */
180 char token[1024], /* Token from file */
181 *tokenptr, /* Pointer into token */
182 temp[1024], /* Temporary string */
183 *tempptr; /* Pointer into temp string */
184 ipp_t *request; /* IPP request */
185 ipp_t *response; /* IPP response */
186 ipp_op_t op; /* Operation */
187 ipp_tag_t group; /* Current group */
188 ipp_tag_t value; /* Current value type */
189 ipp_attribute_t *attrptr; /* Attribute pointer */
190 char attr[128]; /* Attribute name */
191 int num_statuses; /* Number of valid status codes */
192 ipp_status_t statuses[100]; /* Valid status codes */
193 int num_expects; /* Number of expected attributes */
194 char *expects[100]; /* Expected attributes */
195 int num_displayed; /* Number of displayed attributes */
196 char *displayed[100]; /* Displayed attributes */
197 char name[1024]; /* Name of test */
198 char filename[1024]; /* Filename */
199 int pass; /* Did we pass the test? */
200 int job_id; /* Job ID from last operation */
201 int subscription_id; /* Subscription ID from last operation */
202
203
204 /*
205 * Open the test file...
206 */
207
208 if ((fp = fopen(testfile, "r")) == NULL)
209 {
210 printf("Unable to open test file %s - %s\n", testfile, strerror(errno));
211 return (0);
212 }
213
214 /*
215 * Connect to the server...
216 */
217
52f6f666 218 httpSeparateURI(HTTP_URI_CODING_ALL, uri, scheme, sizeof(scheme), userpass,
a4d04587 219 sizeof(userpass), server, sizeof(server), &port, resource,
220 sizeof(resource));
ef416fc2 221 if ((http = httpConnect(server, port)) == NULL)
222 {
223 printf("Unable to connect to %s on port %d - %s\n", server, port,
224 strerror(errno));
91c84a35 225 fclose(fp);
ef416fc2 226 return (0);
227 }
228
229 /*
230 * Loop on tests...
231 */
232
233 printf("\"%s\":\n", testfile);
234 pass = 1;
235 job_id = 0;
236 subscription_id = 0;
d2354e63 237 version = 11;
ef416fc2 238 linenum = 1;
239
240 while (get_token(fp, token, sizeof(token), &linenum) != NULL)
241 {
242 /*
243 * Expect an open brace...
244 */
245
246 if (strcmp(token, "{"))
247 {
248 printf("Unexpected token %s seen on line %d - aborting test!\n", token,
249 linenum);
250 httpClose(http);
251 return (0);
252 }
253
254 /*
255 * Initialize things...
256 */
257
52f6f666 258 httpSeparateURI(HTTP_URI_CODING_ALL, uri, scheme, sizeof(scheme), userpass,
a4d04587 259 sizeof(userpass), server, sizeof(server), &port, resource,
260 sizeof(resource));
ef416fc2 261
262 request = ippNew();
263 op = (ipp_op_t)0;
264 group = IPP_TAG_ZERO;
ef416fc2 265 num_statuses = 0;
266 num_expects = 0;
267 num_displayed = 0;
268 filename[0] = '\0';
269
270 strcpy(name, testfile);
271 if (strrchr(name, '.') != NULL)
272 *strrchr(name, '.') = '\0';
273
274 /*
275 * Parse until we see a close brace...
276 */
277
278 while (get_token(fp, token, sizeof(token), &linenum) != NULL)
279 {
280 if (!strcmp(token, "}"))
281 break;
282 else if (!strcasecmp(token, "NAME"))
283 {
284 /*
285 * Name of test...
286 */
287
288 get_token(fp, name, sizeof(name), &linenum);
289 }
290 else if (!strcasecmp(token, "VERSION"))
291 {
292 /*
293 * IPP version number for test...
294 */
295
d2354e63
MS
296 int major, minor; /* Major/minor IPP version */
297
298
ef416fc2 299 get_token(fp, temp, sizeof(temp), &linenum);
d2354e63
MS
300 if (sscanf(temp, "%d.%d", &major, &minor) == 2 &&
301 major >= 0 && minor >= 0 && minor < 10)
302 version = major * 10 + minor;
303 else
304 {
305 printf("Bad version %s seen on line %d - aborting test!\n", token,
306 linenum);
307 httpClose(http);
308 ippDelete(request);
309 return (0);
310 }
ef416fc2 311 }
312 else if (!strcasecmp(token, "RESOURCE"))
313 {
314 /*
315 * Resource name...
316 */
317
318 get_token(fp, resource, sizeof(resource), &linenum);
319 }
320 else if (!strcasecmp(token, "OPERATION"))
321 {
322 /*
323 * Operation...
324 */
325
326 get_token(fp, token, sizeof(token), &linenum);
327 op = ippOpValue(token);
328 }
329 else if (!strcasecmp(token, "GROUP"))
330 {
331 /*
332 * Attribute group...
333 */
334
335 get_token(fp, token, sizeof(token), &linenum);
1ff0402e 336 value = ippTagValue(token);
ef416fc2 337
338 if (value == group)
339 ippAddSeparator(request);
340
341 group = value;
342 }
343 else if (!strcasecmp(token, "DELAY"))
344 {
345 /*
346 * Delay before operation...
347 */
348
349 int delay;
350
351 get_token(fp, token, sizeof(token), &linenum);
352 if ((delay = atoi(token)) > 0)
353 sleep(delay);
354 }
355 else if (!strcasecmp(token, "ATTR"))
356 {
357 /*
358 * Attribute...
359 */
360
361 get_token(fp, token, sizeof(token), &linenum);
1ff0402e 362 value = ippTagValue(token);
ef416fc2 363 get_token(fp, attr, sizeof(attr), &linenum);
364 get_token(fp, temp, sizeof(temp), &linenum);
365
366 token[sizeof(token) - 1] = '\0';
367
368 for (tempptr = temp, tokenptr = token;
369 *tempptr && tokenptr < (token + sizeof(token) - 1);)
370 if (*tempptr == '$')
371 {
372 /*
373 * Substitute a string/number...
374 */
375
376 if (!strncasecmp(tempptr + 1, "uri", 3))
377 {
378 strlcpy(tokenptr, uri, sizeof(token) - (tokenptr - token));
379 tempptr += 4;
380 }
52f6f666
MS
381 else if (!strncasecmp(tempptr + 1, "scheme", 6) ||
382 !strncasecmp(tempptr + 1, "method", 6))
ef416fc2 383 {
52f6f666 384 strlcpy(tokenptr, scheme, sizeof(token) - (tokenptr - token));
ef416fc2 385 tempptr += 7;
386 }
387 else if (!strncasecmp(tempptr + 1, "username", 8))
388 {
389 strlcpy(tokenptr, userpass, sizeof(token) - (tokenptr - token));
390 tempptr += 9;
391 }
392 else if (!strncasecmp(tempptr + 1, "hostname", 8))
393 {
394 strlcpy(tokenptr, server, sizeof(token) - (tokenptr - token));
395 tempptr += 9;
396 }
397 else if (!strncasecmp(tempptr + 1, "port", 4))
398 {
399 snprintf(tokenptr, sizeof(token) - (tokenptr - token),
400 "%d", port);
401 tempptr += 5;
402 }
403 else if (!strncasecmp(tempptr + 1, "resource", 8))
404 {
405 strlcpy(tokenptr, resource, sizeof(token) - (tokenptr - token));
406 tempptr += 9;
407 }
408 else if (!strncasecmp(tempptr + 1, "job-id", 6))
409 {
410 snprintf(tokenptr, sizeof(token) - (tokenptr - token),
411 "%d", job_id);
412 tempptr += 7;
413 }
414 else if (!strncasecmp(tempptr + 1, "notify-subscription-id", 22))
415 {
416 snprintf(tokenptr, sizeof(token) - (tokenptr - token),
417 "%d", subscription_id);
418 tempptr += 23;
419 }
420 else if (!strncasecmp(tempptr + 1, "user", 4))
421 {
422 strlcpy(tokenptr, cupsUser(), sizeof(token) - (tokenptr - token));
423 tempptr += 5;
424 }
b94498cf 425 else if (!strncasecmp(tempptr + 1, "ENV[", 4))
426 {
427 char *end; /* End of $ENV[name] */
428
429
430 if ((end = strchr(tempptr + 5, ']')) != NULL)
431 {
432 *end++ = '\0';
433 strlcpy(tokenptr,
434 getenv(tempptr + 5) ? getenv(tempptr + 5) : tempptr + 5,
435 sizeof(token) - (tokenptr - token));
436 tempptr = end;
437 }
438 else
439 {
440 *tokenptr++ = *tempptr++;
441 *tokenptr = '\0';
442 }
443 }
ef416fc2 444 else
445 {
b94498cf 446 *tokenptr++ = *tempptr++;
ef416fc2 447 *tokenptr = '\0';
448 }
449
450 tokenptr += strlen(tokenptr);
451 }
452 else
453 {
454 *tokenptr++ = *tempptr++;
455 *tokenptr = '\0';
456 }
457
458 switch (value)
459 {
460 case IPP_TAG_BOOLEAN :
461 if (!strcasecmp(token, "true"))
462 ippAddBoolean(request, group, attr, 1);
463 else
464 ippAddBoolean(request, group, attr, atoi(token));
465 break;
466
467 case IPP_TAG_INTEGER :
468 case IPP_TAG_ENUM :
469 ippAddInteger(request, group, value, attr, atoi(token));
470 break;
471
472 case IPP_TAG_RESOLUTION :
473 puts(" ERROR: resolution tag not yet supported!");
474 break;
475
476 case IPP_TAG_RANGE :
477 puts(" ERROR: range tag not yet supported!");
478 break;
479
480 default :
481 if (!strchr(token, ','))
482 ippAddString(request, group, value, attr, NULL, token);
483 else
484 {
485 /*
486 * Multiple string values...
487 */
488
489 int num_values; /* Number of values */
490 char *values[100], /* Values */
491 *ptr; /* Pointer to next value */
492
493
494 values[0] = token;
495 num_values = 1;
496
497 for (ptr = strchr(token, ','); ptr; ptr = strchr(ptr, ','))
498 {
499 *ptr++ = '\0';
500 values[num_values] = ptr;
501 num_values ++;
502 }
503
504 ippAddStrings(request, group, value, attr, num_values,
505 NULL, (const char **)values);
506 }
507 break;
508 }
509 }
510 else if (!strcasecmp(token, "FILE"))
511 {
512 /*
513 * File...
514 */
515
516 get_token(fp, filename, sizeof(filename), &linenum);
517 }
518 else if (!strcasecmp(token, "STATUS") &&
519 num_statuses < (int)(sizeof(statuses) / sizeof(statuses[0])))
520 {
521 /*
522 * Status...
523 */
524
525 get_token(fp, token, sizeof(token), &linenum);
526 statuses[num_statuses] = ippErrorValue(token);
527 num_statuses ++;
528 }
529 else if (!strcasecmp(token, "EXPECT") &&
530 num_expects < (int)(sizeof(expects) / sizeof(expects[0])))
531 {
532 /*
533 * Expected attributes...
534 */
535
536 get_token(fp, token, sizeof(token), &linenum);
537 expects[num_expects] = strdup(token);
538 num_expects ++;
539 }
540 else if (!strcasecmp(token, "DISPLAY") &&
541 num_displayed < (int)(sizeof(displayed) / sizeof(displayed[0])))
542 {
543 /*
544 * Display attributes...
545 */
546
547 get_token(fp, token, sizeof(token), &linenum);
548 displayed[num_displayed] = strdup(token);
549 num_displayed ++;
550 }
551 else
552 {
553 printf("Unexpected token %s seen on line %d - aborting test!\n", token,
554 linenum);
555 httpClose(http);
556 ippDelete(request);
557 return (0);
558 }
559 }
560
561 /*
562 * Submit the IPP request...
563 */
564
d2354e63
MS
565 request->request.op.version[0] = version / 10;
566 request->request.op.version[1] = version % 10;
ef416fc2 567 request->request.op.operation_id = op;
568 request->request.op.request_id = 1;
569
bd7854cb 570 if (Verbosity)
571 {
572 printf("%s:\n", ippOpString(op));
573
574 for (attrptr = request->attrs; attrptr; attrptr = attrptr->next)
575 print_attr(attrptr);
576 }
ef416fc2 577
578 printf(" %-60.60s [", name);
579 fflush(stdout);
580
581 if (filename[0])
582 response = cupsDoFileRequest(http, request, resource, filename);
583 else
b94498cf 584 response = cupsDoIORequest(http, request, resource, -1,
585 Verbosity ? 1 : -1);
ef416fc2 586
587 if (response == NULL)
588 {
589 time_t curtime;
590
591 curtime = time(NULL);
592
593 puts("FAIL]");
594 printf(" ERROR %04x (%s) @ %s\n", cupsLastError(),
bd7854cb 595 cupsLastErrorString(), ctime(&curtime));
ef416fc2 596 pass = 0;
597 }
598 else
599 {
600 if ((attrptr = ippFindAttribute(response, "job-id",
601 IPP_TAG_INTEGER)) != NULL)
602 job_id = attrptr->values[0].integer;
603
604 if ((attrptr = ippFindAttribute(response, "notify-subscription-id",
605 IPP_TAG_INTEGER)) != NULL)
606 subscription_id = attrptr->values[0].integer;
607
608 for (i = 0; i < num_statuses; i ++)
609 if (response->request.status.status_code == statuses[i])
610 break;
611
612 if (i == num_statuses && num_statuses > 0)
613 pass = 0;
614 else
615 {
616 for (i = 0; i < num_expects; i ++)
617 if (ippFindAttribute(response, expects[i], IPP_TAG_ZERO) == NULL)
618 {
619 pass = 0;
620 break;
621 }
622 }
623
624 if (pass)
625 {
626 puts("PASS]");
627 printf(" RECEIVED: %lu bytes in response\n",
628 (unsigned long)ippLength(response));
629
e00b005a 630 if (Verbosity)
631 {
632 for (attrptr = response->attrs; attrptr != NULL; attrptr = attrptr->next)
633 print_attr(attrptr);
634 }
635 else if (num_displayed > 0)
ef416fc2 636 {
637 for (attrptr = response->attrs; attrptr != NULL; attrptr = attrptr->next)
638 if (attrptr->name)
639 {
640 for (i = 0; i < num_displayed; i ++)
641 if (!strcmp(displayed[i], attrptr->name))
642 {
643 print_attr(attrptr);
644 break;
645 }
646 }
647 }
648 }
649 else
650 {
651 puts("FAIL]");
652 printf(" RECEIVED: %lu bytes in response\n",
653 (unsigned long)ippLength(response));
654
655 for (i = 0; i < num_statuses; i ++)
656 if (response->request.status.status_code == statuses[i])
657 break;
658
659 if (i == num_statuses && num_statuses > 0)
660 puts(" BAD STATUS");
661
662 printf(" status-code = %04x (%s)\n",
b94498cf 663 cupsLastError(), ippErrorString(cupsLastError()));
ef416fc2 664
665 for (i = 0; i < num_expects; i ++)
666 if (ippFindAttribute(response, expects[i], IPP_TAG_ZERO) == NULL)
667 printf(" EXPECTED: %s\n", expects[i]);
668
669 for (attrptr = response->attrs; attrptr != NULL; attrptr = attrptr->next)
670 print_attr(attrptr);
671 }
672
673 ippDelete(response);
674 }
675
676 for (i = 0; i < num_expects; i ++)
677 free(expects[i]);
678
679 if (!pass)
680 break;
681 }
682
683 fclose(fp);
684 httpClose(http);
685
686 return (pass);
687}
688
689
ef416fc2 690/*
691 * 'get_token()' - Get a token from a file.
692 */
693
694char * /* O - Token from file or NULL on EOF */
695get_token(FILE *fp, /* I - File to read from */
696 char *buf, /* I - Buffer to read into */
697 int buflen, /* I - Length of buffer */
698 int *linenum) /* IO - Current line number */
699{
700 int ch, /* Character from file */
701 quote; /* Quoting character */
702 char *bufptr, /* Pointer into buffer */
703 *bufend; /* End of buffer */
704
705
706 for (;;)
707 {
708 /*
709 * Skip whitespace...
710 */
711
712 while (isspace(ch = getc(fp)))
713 {
714 if (ch == '\n')
715 (*linenum) ++;
716 }
717
718 /*
719 * Read a token...
720 */
721
722 if (ch == EOF)
723 return (NULL);
724 else if (ch == '\'' || ch == '\"')
725 {
726 /*
727 * Quoted text...
728 */
729
730 quote = ch;
731 bufptr = buf;
732 bufend = buf + buflen - 1;
733
734 while ((ch = getc(fp)) != EOF)
735 if (ch == quote)
736 break;
737 else if (bufptr < bufend)
738 *bufptr++ = ch;
739
740 *bufptr = '\0';
741 return (buf);
742 }
743 else if (ch == '#')
744 {
745 /*
746 * Comment...
747 */
748
749 while ((ch = getc(fp)) != EOF)
750 if (ch == '\n')
751 break;
752
753 (*linenum) ++;
754 }
755 else
756 {
757 /*
758 * Whitespace delimited text...
759 */
760
761 ungetc(ch, fp);
762
763 bufptr = buf;
764 bufend = buf + buflen - 1;
765
766 while ((ch = getc(fp)) != EOF)
767 if (isspace(ch) || ch == '#')
768 break;
769 else if (bufptr < bufend)
770 *bufptr++ = ch;
771
772 if (ch == '#')
773 ungetc(ch, fp);
774
775 *bufptr = '\0';
776 return (buf);
777 }
778 }
779}
780
781
782/*
783 * 'print_attr()' - Print an attribute on the screen.
784 */
785
786void
787print_attr(ipp_attribute_t *attr) /* I - Attribute to print */
788{
789 int i; /* Looping var */
790
791
792 if (attr->name == NULL)
793 {
794 puts(" -- separator --");
795 return;
796 }
797
d09495fa 798 printf(" %s (%s%s) = ", attr->name,
799 attr->num_values > 1 ? "1setOf " : "",
1ff0402e 800 ippTagString(attr->value_tag));
ef416fc2 801
802 switch (attr->value_tag)
803 {
804 case IPP_TAG_INTEGER :
805 case IPP_TAG_ENUM :
806 for (i = 0; i < attr->num_values; i ++)
807 printf("%d ", attr->values[i].integer);
808 break;
809
810 case IPP_TAG_BOOLEAN :
811 for (i = 0; i < attr->num_values; i ++)
812 if (attr->values[i].boolean)
813 printf("true ");
814 else
815 printf("false ");
816 break;
817
818 case IPP_TAG_NOVALUE :
819 printf("novalue");
820 break;
821
822 case IPP_TAG_RANGE :
823 for (i = 0; i < attr->num_values; i ++)
824 printf("%d-%d ", attr->values[i].range.lower,
825 attr->values[i].range.upper);
826 break;
827
828 case IPP_TAG_RESOLUTION :
829 for (i = 0; i < attr->num_values; i ++)
830 printf("%dx%d%s ", attr->values[i].resolution.xres,
831 attr->values[i].resolution.yres,
832 attr->values[i].resolution.units == IPP_RES_PER_INCH ?
833 "dpi" : "dpc");
834 break;
835
836 case IPP_TAG_STRING :
837 case IPP_TAG_TEXT :
838 case IPP_TAG_NAME :
839 case IPP_TAG_KEYWORD :
840 case IPP_TAG_CHARSET :
841 case IPP_TAG_URI :
842 case IPP_TAG_MIMETYPE :
843 case IPP_TAG_LANGUAGE :
844 for (i = 0; i < attr->num_values; i ++)
845 printf("\"%s\" ", attr->values[i].string.text);
846 break;
847
848 case IPP_TAG_TEXTLANG :
849 case IPP_TAG_NAMELANG :
850 for (i = 0; i < attr->num_values; i ++)
851 printf("\"%s\",%s ", attr->values[i].string.text,
852 attr->values[i].string.charset);
853 break;
854
d2354e63
MS
855 case IPP_TAG_BEGIN_COLLECTION :
856 for (i = 0; i < attr->num_values; i ++)
857 {
858 if (i)
859 putchar(' ');
860
861 print_col(attr->values[i].collection);
862 }
863 break;
864
ef416fc2 865 default :
866 break; /* anti-compiler-warning-code */
867 }
868
869 putchar('\n');
870}
871
872
d2354e63
MS
873/*
874 * 'print_col()' - Print a collection attribute on the screen.
875 */
876
877void
878print_col(ipp_t *col) /* I - Collection attribute to print */
879{
880 int i; /* Looping var */
881 ipp_attribute_t *attr; /* Current attribute in collection */
882
883
884 putchar('{');
885 for (attr = col->attrs; attr; attr = attr->next)
886 {
887 printf("%s(%s%s)=", attr->name, attr->num_values > 1 ? "1setOf " : "",
888 ippTagString(attr->value_tag));
889
890 switch (attr->value_tag)
891 {
892 case IPP_TAG_INTEGER :
893 case IPP_TAG_ENUM :
894 for (i = 0; i < attr->num_values; i ++)
895 printf("%d ", attr->values[i].integer);
896 break;
897
898 case IPP_TAG_BOOLEAN :
899 for (i = 0; i < attr->num_values; i ++)
900 if (attr->values[i].boolean)
901 printf("true ");
902 else
903 printf("false ");
904 break;
905
906 case IPP_TAG_NOVALUE :
907 printf("novalue");
908 break;
909
910 case IPP_TAG_RANGE :
911 for (i = 0; i < attr->num_values; i ++)
912 printf("%d-%d ", attr->values[i].range.lower,
913 attr->values[i].range.upper);
914 break;
915
916 case IPP_TAG_RESOLUTION :
917 for (i = 0; i < attr->num_values; i ++)
918 printf("%dx%d%s ", attr->values[i].resolution.xres,
919 attr->values[i].resolution.yres,
920 attr->values[i].resolution.units == IPP_RES_PER_INCH ?
921 "dpi" : "dpc");
922 break;
923
924 case IPP_TAG_STRING :
925 case IPP_TAG_TEXT :
926 case IPP_TAG_NAME :
927 case IPP_TAG_KEYWORD :
928 case IPP_TAG_CHARSET :
929 case IPP_TAG_URI :
930 case IPP_TAG_MIMETYPE :
931 case IPP_TAG_LANGUAGE :
932 for (i = 0; i < attr->num_values; i ++)
933 printf("\"%s\" ", attr->values[i].string.text);
934 break;
935
936 case IPP_TAG_TEXTLANG :
937 case IPP_TAG_NAMELANG :
938 for (i = 0; i < attr->num_values; i ++)
939 printf("\"%s\",%s ", attr->values[i].string.text,
940 attr->values[i].string.charset);
941 break;
942
943 case IPP_TAG_BEGIN_COLLECTION :
944 for (i = 0; i < attr->num_values; i ++)
945 {
946 print_col(attr->values[i].collection);
947 putchar(' ');
948 }
949 break;
950
951 default :
952 break; /* anti-compiler-warning-code */
953 }
954 }
955
956 putchar('}');
957}
958
959
ef416fc2 960/*
e00b005a 961 * 'usage()' - Show program usage.
962 */
963
964void
965usage(const char *option) /* I - Option string or NULL */
966{
967 if (option)
968 fprintf(stderr, "ipptest: Unknown option \"%s\"!\n", option);
969
970 fputs("Usage: ipptest [options] URL testfile [ ... testfileN ]\n", stderr);
971 fputs("Options:\n", stderr);
972 fputs("\n", stderr);
8ca02f3c 973 fputs("-i N Repeat the last test file once every N seconds.\n", stderr);
974 fputs("-v Show all attributes in response, even on success.\n", stderr);
e00b005a 975
976 exit(1);
977}
978
979
980/*
b19ccc9e 981 * End of "$Id: ipptest.c 7847 2008-08-19 04:22:14Z mike $".
ef416fc2 982 */