/*
- * "$Id$"
- *
* IPP test program for CUPS.
*
- * Copyright 2007-2014 by Apple Inc.
- * Copyright 1997-2005 by Easy Software Products.
- *
- * These coded instructions, statements, and computer programs are the
- * property of Apple Inc. and are protected by Federal copyright
- * law. Distribution and use rights are outlined in the file "LICENSE.txt"
- * which should have been included with this file. If this file is
- * file is missing or damaged, see the license at "http://www.cups.org/".
+ * Copyright © 2007-2019 by Apple Inc.
+ * Copyright © 1997-2005 by Easy Software Products.
*
- * This file is subject to the Apple OS-Developed Software exception.
+ * Licensed under Apache License v2.0. See the file "LICENSE" for more
+ * information.
*/
/*
#include "file.h"
#include "string-private.h"
#include "ipp-private.h"
-#ifdef WIN32
+#ifdef _WIN32
# include <io.h>
#else
# include <unistd.h>
# include <fcntl.h>
-#endif /* WIN32 */
+#endif /* _WIN32 */
/*
0x01, 0x01, /* IPP version */
0x00, 0x02, /* Print-Job operation */
0x00, 0x00, 0x00, 0x01,
- /* Request ID */
+ /* Request ID */
IPP_TAG_OPERATION,
IPP_TAG_JOB, /* job group tag */
IPP_TAG_BEGIN_COLLECTION,
- /* begCollection tag */
+ /* begCollection tag */
0x00, 0x09, /* Name length + name */
'm', 'e', 'd', 'i', 'a', '-', 'c', 'o', 'l',
0x00, 0x00, /* No value */
0x00, 0x0a, /* Value length + value */
'm', 'e', 'd', 'i', 'a', '-', 's', 'i', 'z', 'e',
IPP_TAG_BEGIN_COLLECTION,
- /* begCollection tag */
+ /* begCollection tag */
0x00, 0x00, /* Name length + name */
0x00, 0x00, /* No value */
IPP_TAG_MEMBERNAME,
- /* memberAttrName tag */
+ /* memberAttrName tag */
0x00, 0x00, /* No name */
0x00, 0x0b, /* Value length + value */
'x', '-', 'd', 'i', 'm', 'e', 'n', 's', 'i', 'o', 'n',
0x00, 0x04, /* Value length + value */
0x00, 0x00, 0x54, 0x56,
IPP_TAG_MEMBERNAME,
- /* memberAttrName tag */
+ /* memberAttrName tag */
0x00, 0x00, /* No name */
0x00, 0x0b, /* Value length + value */
'y', '-', 'd', 'i', 'm', 'e', 'n', 's', 'i', 'o', 'n',
0x00, 0x04, /* Value length + value */
0x00, 0x00, 0x6d, 0x24,
IPP_TAG_END_COLLECTION,
- /* endCollection tag */
+ /* endCollection tag */
0x00, 0x00, /* No name */
0x00, 0x00, /* No value */
IPP_TAG_MEMBERNAME, /* memberAttrName tag */
0x00, 0x05, /* Value length + value */
'p', 'l', 'a', 'i', 'n',
IPP_TAG_END_COLLECTION,
- /* endCollection tag */
+ /* endCollection tag */
0x00, 0x00, /* No name */
0x00, 0x00, /* No value */
IPP_TAG_BEGIN_COLLECTION,
- /* begCollection tag */
+ /* begCollection tag */
0x00, 0x00, /* No name */
0x00, 0x00, /* No value */
IPP_TAG_MEMBERNAME, /* memberAttrName tag */
0x00, 0x0a, /* Value length + value */
'm', 'e', 'd', 'i', 'a', '-', 's', 'i', 'z', 'e',
IPP_TAG_BEGIN_COLLECTION,
- /* begCollection tag */
+ /* begCollection tag */
0x00, 0x00, /* Name length + name */
0x00, 0x00, /* No value */
IPP_TAG_MEMBERNAME,
- /* memberAttrName tag */
+ /* memberAttrName tag */
0x00, 0x00, /* No name */
0x00, 0x0b, /* Value length + value */
'x', '-', 'd', 'i', 'm', 'e', 'n', 's', 'i', 'o', 'n',
0x00, 0x04, /* Value length + value */
0x00, 0x00, 0x52, 0x08,
IPP_TAG_MEMBERNAME,
- /* memberAttrName tag */
+ /* memberAttrName tag */
0x00, 0x00, /* No name */
0x00, 0x0b, /* Value length + value */
'y', '-', 'd', 'i', 'm', 'e', 'n', 's', 'i', 'o', 'n',
0x00, 0x04, /* Value length + value */
0x00, 0x00, 0x74, 0x04,
IPP_TAG_END_COLLECTION,
- /* endCollection tag */
+ /* endCollection tag */
0x00, 0x00, /* No name */
0x00, 0x00, /* No value */
IPP_TAG_MEMBERNAME, /* memberAttrName tag */
0x00, 0x06, /* Value length + value */
'g', 'l', 'o', 's', 's', 'y',
IPP_TAG_END_COLLECTION,
- /* endCollection tag */
+ /* endCollection tag */
+ 0x00, 0x00, /* No name */
+ 0x00, 0x00, /* No value */
+
+ IPP_TAG_END /* end tag */
+ };
+static ipp_uchar_t bad_collection[] = /* Collection buffer (bad encoding) */
+ {
+ 0x01, 0x01, /* IPP version */
+ 0x00, 0x02, /* Print-Job operation */
+ 0x00, 0x00, 0x00, 0x01,
+ /* Request ID */
+
+ IPP_TAG_OPERATION,
+
+ IPP_TAG_CHARSET,
+ 0x00, 0x12, /* Name length + name */
+ 'a','t','t','r','i','b','u','t','e','s','-',
+ 'c','h','a','r','s','e','t',
+ 0x00, 0x05, /* Value length + value */
+ 'u','t','f','-','8',
+
+ IPP_TAG_LANGUAGE,
+ 0x00, 0x1b, /* Name length + name */
+ 'a','t','t','r','i','b','u','t','e','s','-',
+ 'n','a','t','u','r','a','l','-','l','a','n',
+ 'g','u','a','g','e',
+ 0x00, 0x02, /* Value length + value */
+ 'e','n',
+
+ IPP_TAG_URI,
+ 0x00, 0x0b, /* Name length + name */
+ 'p','r','i','n','t','e','r','-','u','r','i',
+ 0x00, 0x1c, /* Value length + value */
+ 'i','p','p',':','/','/','l','o','c','a','l',
+ 'h','o','s','t','/','p','r','i','n','t','e',
+ 'r','s','/','f','o','o',
+
+ IPP_TAG_JOB, /* job group tag */
+
+ IPP_TAG_BEGIN_COLLECTION,
+ /* begCollection tag */
+ 0x00, 0x09, /* Name length + name */
+ 'm', 'e', 'd', 'i', 'a', '-', 'c', 'o', 'l',
+ 0x00, 0x00, /* No value */
+ IPP_TAG_BEGIN_COLLECTION,
+ /* begCollection tag */
+ 0x00, 0x0a, /* Name length + name */
+ 'm', 'e', 'd', 'i', 'a', '-', 's', 'i', 'z', 'e',
+ 0x00, 0x00, /* No value */
+ IPP_TAG_INTEGER, /* integer tag */
+ 0x00, 0x0b, /* Name length + name */
+ 'x', '-', 'd', 'i', 'm', 'e', 'n', 's', 'i', 'o', 'n',
+ 0x00, 0x04, /* Value length + value */
+ 0x00, 0x00, 0x54, 0x56,
+ IPP_TAG_INTEGER, /* integer tag */
+ 0x00, 0x0b, /* Name length + name */
+ 'y', '-', 'd', 'i', 'm', 'e', 'n', 's', 'i', 'o', 'n',
+ 0x00, 0x04, /* Value length + value */
+ 0x00, 0x00, 0x6d, 0x24,
+ IPP_TAG_END_COLLECTION,
+ /* endCollection tag */
+ 0x00, 0x00, /* No name */
+ 0x00, 0x00, /* No value */
+ IPP_TAG_END_COLLECTION,
+ /* endCollection tag */
0x00, 0x00, /* No name */
0x00, 0x00, /* No value */
0x01, 0x01, /* IPP version */
0x00, 0x02, /* Print-Job operation */
0x00, 0x00, 0x00, 0x01,
- /* Request ID */
+ /* Request ID */
IPP_TAG_OPERATION,
void hex_dump(const char *title, ipp_uchar_t *buffer, size_t bytes);
void print_attributes(ipp_t *ipp, int indent);
ssize_t read_cb(_ippdata_t *data, ipp_uchar_t *buffer, size_t bytes);
+ssize_t read_hex(cups_file_t *fp, ipp_uchar_t *buffer, size_t bytes);
+int token_cb(_ipp_file_t *f, _ipp_vars_t *v, void *user_data, const char *token);
ssize_t write_cb(_ippdata_t *data, ipp_uchar_t *buffer, size_t bytes);
}
}
+ /*
+ * Test hierarchical find...
+ */
+
+ fputs("ippFindAttribute(media-col/media-size/x-dimension): ", stdout);
+ if ((attr = ippFindAttribute(request, "media-col/media-size/x-dimension", IPP_TAG_INTEGER)) != NULL)
+ {
+ if (ippGetInteger(attr, 0) != 21590)
+ {
+ printf("FAIL (wrong value for x-dimension - %d)\n", ippGetInteger(attr, 0));
+ status = 1;
+ }
+ else
+ puts("PASS");
+ }
+ else
+ {
+ puts("FAIL (not found)");
+ status = 1;
+ }
+
+ fputs("ippFindNextAttribute(media-col/media-size/x-dimension): ", stdout);
+ if ((attr = ippFindNextAttribute(request, "media-col/media-size/x-dimension", IPP_TAG_INTEGER)) != NULL)
+ {
+ if (ippGetInteger(attr, 0) != 21000)
+ {
+ printf("FAIL (wrong value for x-dimension - %d)\n", ippGetInteger(attr, 0));
+ status = 1;
+ }
+ else
+ puts("PASS");
+ }
+ else
+ {
+ puts("FAIL (not found)");
+ status = 1;
+ }
+
+ fputs("ippFindNextAttribute(media-col/media-size/x-dimension) again: ", stdout);
+ if ((attr = ippFindNextAttribute(request, "media-col/media-size/x-dimension", IPP_TAG_INTEGER)) != NULL)
+ {
+ printf("FAIL (got %d, expected nothing)\n", ippGetInteger(attr, 0));
+ status = 1;
+ }
+ else
+ puts("PASS");
+
ippDelete(request);
+ /*
+ * Read the bad collection data and confirm we get an error...
+ */
+
+ fputs("Read Bad Collection from Memory: ", stdout);
+
+ request = ippNew();
+ data.rpos = 0;
+ data.wused = sizeof(bad_collection);
+ data.wsize = sizeof(bad_collection);
+ data.wbuffer = bad_collection;
+
+ while ((state = ippReadIO(&data, (ipp_iocb_t)read_cb, 1, NULL, request)) != IPP_STATE_DATA)
+ if (state == IPP_STATE_ERROR)
+ break;
+
+ if (state != IPP_STATE_ERROR)
+ puts("FAIL (read successful)");
+ else
+ puts("PASS");
+
/*
* Read the mixed data and confirm we converted everything to rangeOfInteger
* values...
*/
- printf("Read Mixed integer/rangeOfInteger from Memory: ");
+ fputs("Read Mixed integer/rangeOfInteger from Memory: ", stdout);
request = ippNew();
data.rpos = 0;
for (i = 1; i < (size_t)argc; i ++)
{
- if ((fp = cupsFileOpen(argv[i], "r")) == NULL)
+ if (strlen(argv[i]) > 5 && !strcmp(argv[i] + strlen(argv[i]) - 5, ".test"))
{
- printf("Unable to open \"%s\" - %s\n", argv[i], strerror(errno));
- status = 1;
- continue;
- }
+ /*
+ * Read an ASCII IPP message...
+ */
- request = ippNew();
- while ((state = ippReadIO(fp, (ipp_iocb_t)cupsFileRead, 1, NULL,
- request)) == IPP_STATE_ATTRIBUTE);
+ _ipp_vars_t v; /* IPP variables */
- if (state != IPP_STATE_DATA)
+ _ippVarsInit(&v, NULL, NULL, token_cb);
+ request = _ippFileParse(&v, argv[i], NULL);
+ _ippVarsDeinit(&v);
+ }
+ else if (strlen(argv[i]) > 4 && !strcmp(argv[i] + strlen(argv[i]) - 4, ".hex"))
{
- printf("Error reading IPP message from \"%s\"!\n", argv[i]);
- status = 1;
+ /*
+ * Read a hex-encoded IPP message...
+ */
+
+ if ((fp = cupsFileOpen(argv[i], "r")) == NULL)
+ {
+ printf("Unable to open \"%s\" - %s\n", argv[i], strerror(errno));
+ status = 1;
+ continue;
+ }
+
+ request = ippNew();
+ while ((state = ippReadIO(fp, (ipp_iocb_t)read_hex, 1, NULL, request)) == IPP_STATE_ATTRIBUTE);
+
+ if (state != IPP_STATE_DATA)
+ {
+ printf("Error reading IPP message from \"%s\": %s\n", argv[i], cupsLastErrorString());
+ status = 1;
+
+ ippDelete(request);
+ request = NULL;
+ }
+
+ cupsFileClose(fp);
}
else
+ {
+ /*
+ * Read a raw (binary) IPP message...
+ */
+
+ if ((fp = cupsFileOpen(argv[i], "r")) == NULL)
+ {
+ printf("Unable to open \"%s\" - %s\n", argv[i], strerror(errno));
+ status = 1;
+ continue;
+ }
+
+ request = ippNew();
+ while ((state = ippReadIO(fp, (ipp_iocb_t)cupsFileRead, 1, NULL,
+ request)) == IPP_STATE_ATTRIBUTE);
+
+ if (state != IPP_STATE_DATA)
+ {
+ printf("Error reading IPP message from \"%s\": %s\n", argv[i], cupsLastErrorString());
+ status = 1;
+
+ ippDelete(request);
+ request = NULL;
+ }
+
+ cupsFileClose(fp);
+ }
+
+ if (request)
{
printf("\n%s:\n", argv[i]);
print_attributes(request, 4);
+ ippDelete(request);
}
-
- ippDelete(request);
- cupsFileClose(fp);
}
}
print_attributes(ipp_t *ipp, /* I - IPP request */
int indent) /* I - Indentation */
{
- int i; /* Looping var */
ipp_tag_t group; /* Current group */
ipp_attribute_t *attr; /* Current attribute */
- _ipp_value_t *val; /* Current value */
- static const char * const tags[] = /* Value/group tag strings */
- {
- "reserved-00",
- "operation-attributes-tag",
- "job-attributes-tag",
- "end-of-attributes-tag",
- "printer-attributes-tag",
- "unsupported-attributes-tag",
- "subscription-attributes-tag",
- "event-attributes-tag",
- "reserved-08",
- "reserved-09",
- "reserved-0A",
- "reserved-0B",
- "reserved-0C",
- "reserved-0D",
- "reserved-0E",
- "reserved-0F",
- "unsupported",
- "default",
- "unknown",
- "no-value",
- "reserved-14",
- "not-settable",
- "delete-attr",
- "admin-define",
- "reserved-18",
- "reserved-19",
- "reserved-1A",
- "reserved-1B",
- "reserved-1C",
- "reserved-1D",
- "reserved-1E",
- "reserved-1F",
- "reserved-20",
- "integer",
- "boolean",
- "enum",
- "reserved-24",
- "reserved-25",
- "reserved-26",
- "reserved-27",
- "reserved-28",
- "reserved-29",
- "reserved-2a",
- "reserved-2b",
- "reserved-2c",
- "reserved-2d",
- "reserved-2e",
- "reserved-2f",
- "octetString",
- "dateTime",
- "resolution",
- "rangeOfInteger",
- "begCollection",
- "textWithLanguage",
- "nameWithLanguage",
- "endCollection",
- "reserved-38",
- "reserved-39",
- "reserved-3a",
- "reserved-3b",
- "reserved-3c",
- "reserved-3d",
- "reserved-3e",
- "reserved-3f",
- "reserved-40",
- "textWithoutLanguage",
- "nameWithoutLanguage",
- "reserved-43",
- "keyword",
- "uri",
- "uriScheme",
- "charset",
- "naturalLanguage",
- "mimeMediaType",
- "memberName"
- };
+ char buffer[2048]; /* Value string */
for (group = IPP_TAG_ZERO, attr = ipp->attrs; attr; attr = attr->next)
{
group = attr->group_tag;
- printf("\n%*s%s:\n\n", indent - 4, "", tags[group]);
+ printf("\n%*s%s:\n\n", indent - 4, "", ippTagString(group));
}
- printf("%*s%s (", indent, "", attr->name ? attr->name : "(null)");
- if (attr->num_values > 1)
- printf("1setOf ");
- printf("%s):", tags[attr->value_tag]);
+ ippAttributeString(attr, buffer, sizeof(buffer));
- switch (attr->value_tag)
- {
- case IPP_TAG_ENUM :
- case IPP_TAG_INTEGER :
- for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
- printf(" %d", val->integer);
- putchar('\n');
- break;
-
- case IPP_TAG_BOOLEAN :
- for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
- printf(" %s", val->boolean ? "true" : "false");
- putchar('\n');
- break;
-
- case IPP_TAG_RANGE :
- for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
- printf(" %d-%d", val->range.lower, val->range.upper);
- putchar('\n');
- break;
-
- case IPP_TAG_DATE :
- {
- time_t vtime; /* Date/Time value */
- struct tm *vdate; /* Date info */
- char vstring[256]; /* Formatted time */
-
- for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
- {
- vtime = ippDateToTime(val->date);
- vdate = localtime(&vtime);
- strftime(vstring, sizeof(vstring), "%c", vdate);
- printf(" (%s)", vstring);
- }
- }
- putchar('\n');
- break;
-
- case IPP_TAG_RESOLUTION :
- for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
- printf(" %dx%d%s", val->resolution.xres, val->resolution.yres,
- val->resolution.units == IPP_RES_PER_INCH ? "dpi" : "dpcm");
- putchar('\n');
- break;
-
- case IPP_TAG_STRING :
- case IPP_TAG_TEXTLANG :
- case IPP_TAG_NAMELANG :
- case IPP_TAG_TEXT :
- case IPP_TAG_NAME :
- case IPP_TAG_KEYWORD :
- case IPP_TAG_URI :
- case IPP_TAG_URISCHEME :
- case IPP_TAG_CHARSET :
- case IPP_TAG_LANGUAGE :
- case IPP_TAG_MIMETYPE :
- for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
- printf(" \"%s\"", val->string.text);
- putchar('\n');
- break;
-
- case IPP_TAG_BEGIN_COLLECTION :
- putchar('\n');
-
- for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
- {
- if (i)
- putchar('\n');
- print_attributes(val->collection, indent + 4);
- }
- break;
-
- default :
- printf("UNKNOWN (%d values)\n", attr->num_values);
- break;
- }
+ printf("%*s%s (%s%s): %s\n", indent, "", attr->name ? attr->name : "(null)", attr->num_values > 1 ? "1setOf " : "", ippTagString(attr->value_tag), buffer);
}
}
}
+/*
+ * 'read_hex()' - Read a hex dump of an IPP request.
+ */
+
+ssize_t /* O - Number of bytes read */
+read_hex(cups_file_t *fp, /* I - File to read from */
+ ipp_uchar_t *buffer, /* I - Buffer to read */
+ size_t bytes) /* I - Number of bytes to read */
+{
+ size_t total = 0; /* Total bytes read */
+ static char hex[256] = ""; /* Line from file */
+ static char *hexptr = NULL; /* Pointer in line */
+
+
+ while (total < bytes)
+ {
+ if (!hexptr || (isspace(hexptr[0] & 255) && isspace(hexptr[1] & 255)))
+ {
+ if (!cupsFileGets(fp, hex, sizeof(hex)))
+ break;
+
+ hexptr = hex;
+ while (isxdigit(*hexptr & 255))
+ hexptr ++;
+ while (isspace(*hexptr & 255))
+ hexptr ++;
+
+ if (!isxdigit(*hexptr & 255))
+ {
+ hexptr = NULL;
+ continue;
+ }
+ }
+
+ *buffer++ = (ipp_uchar_t)strtol(hexptr, &hexptr, 16);
+ total ++;
+ }
+
+ return (total == 0 ? -1 : (ssize_t)total);
+}
+
+
+/*
+ * 'token_cb()' - Token callback for ASCII IPP data file parser.
+ */
+
+int /* O - 1 on success, 0 on failure */
+token_cb(_ipp_file_t *f, /* I - IPP file data */
+ _ipp_vars_t *v, /* I - IPP variables */
+ void *user_data, /* I - User data pointer */
+ const char *token) /* I - Token string */
+{
+ (void)v;
+ (void)user_data;
+
+ if (!token)
+ {
+ f->attrs = ippNew();
+ f->group_tag = IPP_TAG_PRINTER;
+ }
+ else
+ {
+ fprintf(stderr, "Unknown directive \"%s\" on line %d of \"%s\".\n", token, f->linenum, f->filename);
+ return (0);
+ }
+
+ return (1);
+}
+
+
/*
* 'write_cb()' - Write data into a buffer.
*/
return ((ssize_t)count);
}
-
-
-/*
- * End of "$Id$".
- */