You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1102 lines
29 KiB

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

/*
* IPP test program for CUPS.
*
* Copyright © 2007-2019 by Apple Inc.
* Copyright © 1997-2005 by Easy Software Products.
*
* Licensed under Apache License v2.0. See the file "LICENSE" for more
* information.
*/
/*
* Include necessary headers...
*/
#include "file.h"
#include "string-private.h"
#include "ipp-private.h"
#ifdef _WIN32
# include <io.h>
#else
# include <unistd.h>
# include <fcntl.h>
#endif /* _WIN32 */
/*
* Local types...
*/
typedef struct _ippdata_t
{
size_t rpos, /* Read position */
wused, /* Bytes used */
wsize; /* Max size of buffer */
ipp_uchar_t *wbuffer; /* Buffer */
} _ippdata_t;
/*
* Local globals...
*/
static ipp_uchar_t collection[] = /* Collection buffer */
{
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_MEMBERNAME, /* memberAttrName tag */
0x00, 0x00, /* No name */
0x00, 0x0a, /* Value length + value */
'm', 'e', 'd', 'i', 'a', '-', 's', 'i', 'z', 'e',
IPP_TAG_BEGIN_COLLECTION,
/* begCollection tag */
0x00, 0x00, /* Name length + name */
0x00, 0x00, /* No value */
IPP_TAG_MEMBERNAME,
/* memberAttrName tag */
0x00, 0x00, /* No name */
0x00, 0x0b, /* Value length + value */
'x', '-', 'd', 'i', 'm', 'e', 'n', 's', 'i', 'o', 'n',
IPP_TAG_INTEGER, /* integer tag */
0x00, 0x00, /* No name */
0x00, 0x04, /* Value length + value */
0x00, 0x00, 0x54, 0x56,
IPP_TAG_MEMBERNAME,
/* memberAttrName tag */
0x00, 0x00, /* No name */
0x00, 0x0b, /* Value length + value */
'y', '-', 'd', 'i', 'm', 'e', 'n', 's', 'i', 'o', 'n',
IPP_TAG_INTEGER, /* integer tag */
0x00, 0x00, /* No name */
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_MEMBERNAME, /* memberAttrName tag */
0x00, 0x00, /* No name */
0x00, 0x0b, /* Value length + value */
'm', 'e', 'd', 'i', 'a', '-', 'c', 'o', 'l', 'o', 'r',
IPP_TAG_KEYWORD, /* keyword tag */
0x00, 0x00, /* No name */
0x00, 0x04, /* Value length + value */
'b', 'l', 'u', 'e',
IPP_TAG_MEMBERNAME, /* memberAttrName tag */
0x00, 0x00, /* No name */
0x00, 0x0a, /* Value length + value */
'm', 'e', 'd', 'i', 'a', '-', 't', 'y', 'p', 'e',
IPP_TAG_KEYWORD, /* keyword tag */
0x00, 0x00, /* No name */
0x00, 0x05, /* Value length + value */
'p', 'l', 'a', 'i', 'n',
IPP_TAG_END_COLLECTION,
/* endCollection tag */
0x00, 0x00, /* No name */
0x00, 0x00, /* No value */
IPP_TAG_BEGIN_COLLECTION,
/* begCollection tag */
0x00, 0x00, /* No name */
0x00, 0x00, /* No value */
IPP_TAG_MEMBERNAME, /* memberAttrName tag */
0x00, 0x00, /* No name */
0x00, 0x0a, /* Value length + value */
'm', 'e', 'd', 'i', 'a', '-', 's', 'i', 'z', 'e',
IPP_TAG_BEGIN_COLLECTION,
/* begCollection tag */
0x00, 0x00, /* Name length + name */
0x00, 0x00, /* No value */
IPP_TAG_MEMBERNAME,
/* memberAttrName tag */
0x00, 0x00, /* No name */
0x00, 0x0b, /* Value length + value */
'x', '-', 'd', 'i', 'm', 'e', 'n', 's', 'i', 'o', 'n',
IPP_TAG_INTEGER, /* integer tag */
0x00, 0x00, /* No name */
0x00, 0x04, /* Value length + value */
0x00, 0x00, 0x52, 0x08,
IPP_TAG_MEMBERNAME,
/* memberAttrName tag */
0x00, 0x00, /* No name */
0x00, 0x0b, /* Value length + value */
'y', '-', 'd', 'i', 'm', 'e', 'n', 's', 'i', 'o', 'n',
IPP_TAG_INTEGER, /* integer tag */
0x00, 0x00, /* No name */
0x00, 0x04, /* Value length + value */
0x00, 0x00, 0x74, 0x04,
IPP_TAG_END_COLLECTION,
/* endCollection tag */
0x00, 0x00, /* No name */
0x00, 0x00, /* No value */
IPP_TAG_MEMBERNAME, /* memberAttrName tag */
0x00, 0x00, /* No name */
0x00, 0x0b, /* Value length + value */
'm', 'e', 'd', 'i', 'a', '-', 'c', 'o', 'l', 'o', 'r',
IPP_TAG_KEYWORD, /* keyword tag */
0x00, 0x00, /* No name */
0x00, 0x05, /* Value length + value */
'p', 'l', 'a', 'i', 'd',
IPP_TAG_MEMBERNAME, /* memberAttrName tag */
0x00, 0x00, /* No name */
0x00, 0x0a, /* Value length + value */
'm', 'e', 'd', 'i', 'a', '-', 't', 'y', 'p', 'e',
IPP_TAG_KEYWORD, /* keyword tag */
0x00, 0x00, /* No name */
0x00, 0x06, /* Value length + value */
'g', 'l', 'o', 's', 's', 'y',
IPP_TAG_END_COLLECTION,
/* 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 */
IPP_TAG_END /* end tag */
};
static ipp_uchar_t mixed[] = /* Mixed value buffer */
{
0x01, 0x01, /* IPP version */
0x00, 0x02, /* Print-Job operation */
0x00, 0x00, 0x00, 0x01,
/* Request ID */
IPP_TAG_OPERATION,
IPP_TAG_INTEGER, /* integer tag */
0x00, 0x1f, /* Name length + name */
'n', 'o', 't', 'i', 'f', 'y', '-', 'l', 'e', 'a', 's', 'e',
'-', 'd', 'u', 'r', 'a', 't', 'i', 'o', 'n', '-', 's', 'u',
'p', 'p', 'o', 'r', 't', 'e', 'd',
0x00, 0x04, /* Value length + value */
0x00, 0x00, 0x00, 0x01,
IPP_TAG_RANGE, /* rangeOfInteger tag */
0x00, 0x00, /* No name */
0x00, 0x08, /* Value length + value */
0x00, 0x00, 0x00, 0x10,
0x00, 0x00, 0x00, 0x20,
IPP_TAG_END /* end tag */
};
/*
* Local functions...
*/
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);
/*
* 'main()' - Main entry.
*/
int /* O - Exit status */
main(int argc, /* I - Number of command-line arguments */
char *argv[]) /* I - Command-line arguments */
{
_ippdata_t data; /* IPP buffer */
ipp_uchar_t buffer[8192]; /* Write buffer data */
ipp_t *cols[2], /* Collections */
*size; /* media-size collection */
ipp_t *request; /* Request */
ipp_attribute_t *media_col, /* media-col attribute */
*media_size, /* media-size attribute */
*attr; /* Other attribute */
ipp_state_t state; /* State */
size_t length; /* Length of data */
cups_file_t *fp; /* File pointer */
size_t i; /* Looping var */
int status; /* Status of tests (0 = success, 1 = fail) */
#ifdef DEBUG
const char *name; /* Option name */
#endif /* DEBUG */
status = 0;
if (argc == 1)
{
/*
* Test request generation code...
*/
printf("Create Sample Request: ");
request = ippNew();
request->request.op.version[0] = 0x01;
request->request.op.version[1] = 0x01;
request->request.op.operation_id = IPP_OP_PRINT_JOB;
request->request.op.request_id = 1;
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
"attributes-charset", NULL, "utf-8");
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
"attributes-natural-language", NULL, "en");
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
"printer-uri", NULL, "ipp://localhost/printers/foo");
cols[0] = ippNew();
size = ippNew();
ippAddInteger(size, IPP_TAG_ZERO, IPP_TAG_INTEGER, "x-dimension", 21590);
ippAddInteger(size, IPP_TAG_ZERO, IPP_TAG_INTEGER, "y-dimension", 27940);
ippAddCollection(cols[0], IPP_TAG_JOB, "media-size", size);
ippDelete(size);
ippAddString(cols[0], IPP_TAG_JOB, IPP_TAG_KEYWORD, "media-color", NULL,
"blue");
ippAddString(cols[0], IPP_TAG_JOB, IPP_TAG_KEYWORD, "media-type", NULL,
"plain");
cols[1] = ippNew();
size = ippNew();
ippAddInteger(size, IPP_TAG_ZERO, IPP_TAG_INTEGER, "x-dimension", 21000);
ippAddInteger(size, IPP_TAG_ZERO, IPP_TAG_INTEGER, "y-dimension", 29700);
ippAddCollection(cols[1], IPP_TAG_JOB, "media-size", size);
ippDelete(size);
ippAddString(cols[1], IPP_TAG_JOB, IPP_TAG_KEYWORD, "media-color", NULL,
"plaid");
ippAddString(cols[1], IPP_TAG_JOB, IPP_TAG_KEYWORD, "media-type", NULL,
"glossy");
ippAddCollections(request, IPP_TAG_JOB, "media-col", 2,
(const ipp_t **)cols);
ippDelete(cols[0]);
ippDelete(cols[1]);
length = ippLength(request);
if (length != sizeof(collection))
{
printf("FAIL - wrong ippLength(), %d instead of %d bytes!\n",
(int)length, (int)sizeof(collection));
status = 1;
}
else
puts("PASS");
/*
* Write test #1...
*/
printf("Write Sample to Memory: ");
data.wused = 0;
data.wsize = sizeof(buffer);
data.wbuffer = buffer;
while ((state = ippWriteIO(&data, (ipp_iocb_t)write_cb, 1, NULL,
request)) != IPP_STATE_DATA)
if (state == IPP_STATE_ERROR)
break;
if (state != IPP_STATE_DATA)
{
printf("FAIL - %d bytes written.\n", (int)data.wused);
status = 1;
}
else if (data.wused != sizeof(collection))
{
printf("FAIL - wrote %d bytes, expected %d bytes!\n", (int)data.wused,
(int)sizeof(collection));
hex_dump("Bytes Written", data.wbuffer, data.wused);
hex_dump("Baseline", collection, sizeof(collection));
status = 1;
}
else if (memcmp(data.wbuffer, collection, data.wused))
{
for (i = 0; i < data.wused; i ++)
if (data.wbuffer[i] != collection[i])
break;
printf("FAIL - output does not match baseline at 0x%04x!\n", (unsigned)i);
hex_dump("Bytes Written", data.wbuffer, data.wused);
hex_dump("Baseline", collection, sizeof(collection));
status = 1;
}
else
puts("PASS");
ippDelete(request);
/*
* Read the data back in and confirm...
*/
printf("Read Sample from Memory: ");
request = ippNew();
data.rpos = 0;
while ((state = ippReadIO(&data, (ipp_iocb_t)read_cb, 1, NULL,
request)) != IPP_STATE_DATA)
if (state == IPP_STATE_ERROR)
break;
length = ippLength(request);
if (state != IPP_STATE_DATA)
{
printf("FAIL - %d bytes read.\n", (int)data.rpos);
status = 1;
}
else if (data.rpos != data.wused)
{
printf("FAIL - read %d bytes, expected %d bytes!\n", (int)data.rpos,
(int)data.wused);
print_attributes(request, 8);
status = 1;
}
else if (length != sizeof(collection))
{
printf("FAIL - wrong ippLength(), %d instead of %d bytes!\n",
(int)length, (int)sizeof(collection));
print_attributes(request, 8);
status = 1;
}
else
puts("PASS");
fputs("ippFindAttribute(media-col): ", stdout);
if ((media_col = ippFindAttribute(request, "media-col",
IPP_TAG_BEGIN_COLLECTION)) == NULL)
{
if ((media_col = ippFindAttribute(request, "media-col",
IPP_TAG_ZERO)) == NULL)
puts("FAIL (not found)");
else
printf("FAIL (wrong type - %s)\n", ippTagString(media_col->value_tag));
status = 1;
}
else if (media_col->num_values != 2)
{
printf("FAIL (wrong count - %d)\n", media_col->num_values);
status = 1;
}
else
puts("PASS");
if (media_col)
{
fputs("ippFindAttribute(media-size 1): ", stdout);
if ((media_size = ippFindAttribute(media_col->values[0].collection,
"media-size",
IPP_TAG_BEGIN_COLLECTION)) == NULL)
{
if ((media_size = ippFindAttribute(media_col->values[0].collection,
"media-col",
IPP_TAG_ZERO)) == NULL)
puts("FAIL (not found)");
else
printf("FAIL (wrong type - %s)\n",
ippTagString(media_size->value_tag));
status = 1;
}
else
{
if ((attr = ippFindAttribute(media_size->values[0].collection,
"x-dimension", IPP_TAG_INTEGER)) == NULL)
{
if ((attr = ippFindAttribute(media_size->values[0].collection,
"x-dimension", IPP_TAG_ZERO)) == NULL)
puts("FAIL (missing x-dimension)");
else
printf("FAIL (wrong type for x-dimension - %s)\n",
ippTagString(attr->value_tag));
status = 1;
}
else if (attr->values[0].integer != 21590)
{
printf("FAIL (wrong value for x-dimension - %d)\n",
attr->values[0].integer);
status = 1;
}
else if ((attr = ippFindAttribute(media_size->values[0].collection,
"y-dimension",
IPP_TAG_INTEGER)) == NULL)
{
if ((attr = ippFindAttribute(media_size->values[0].collection,
"y-dimension", IPP_TAG_ZERO)) == NULL)
puts("FAIL (missing y-dimension)");
else
printf("FAIL (wrong type for y-dimension - %s)\n",
ippTagString(attr->value_tag));
status = 1;
}
else if (attr->values[0].integer != 27940)
{
printf("FAIL (wrong value for y-dimension - %d)\n",
attr->values[0].integer);
status = 1;
}
else
puts("PASS");
}
fputs("ippFindAttribute(media-size 2): ", stdout);
if ((media_size = ippFindAttribute(media_col->values[1].collection,
"media-size",
IPP_TAG_BEGIN_COLLECTION)) == NULL)
{
if ((media_size = ippFindAttribute(media_col->values[1].collection,
"media-col",
IPP_TAG_ZERO)) == NULL)
puts("FAIL (not found)");
else
printf("FAIL (wrong type - %s)\n",
ippTagString(media_size->value_tag));
status = 1;
}
else
{
if ((attr = ippFindAttribute(media_size->values[0].collection,
"x-dimension",
IPP_TAG_INTEGER)) == NULL)
{
if ((attr = ippFindAttribute(media_size->values[0].collection,
"x-dimension", IPP_TAG_ZERO)) == NULL)
puts("FAIL (missing x-dimension)");
else
printf("FAIL (wrong type for x-dimension - %s)\n",
ippTagString(attr->value_tag));
status = 1;
}
else if (attr->values[0].integer != 21000)
{
printf("FAIL (wrong value for x-dimension - %d)\n",
attr->values[0].integer);
status = 1;
}
else if ((attr = ippFindAttribute(media_size->values[0].collection,
"y-dimension",
IPP_TAG_INTEGER)) == NULL)
{
if ((attr = ippFindAttribute(media_size->values[0].collection,
"y-dimension", IPP_TAG_ZERO)) == NULL)
puts("FAIL (missing y-dimension)");
else
printf("FAIL (wrong type for y-dimension - %s)\n",
ippTagString(attr->value_tag));
status = 1;
}
else if (attr->values[0].integer != 29700)
{
printf("FAIL (wrong value for y-dimension - %d)\n",
attr->values[0].integer);
status = 1;
}
else
puts("PASS");
}
}
/*
* 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...
*/
fputs("Read Mixed integer/rangeOfInteger from Memory: ", stdout);
request = ippNew();
data.rpos = 0;
data.wused = sizeof(mixed);
data.wsize = sizeof(mixed);
data.wbuffer = mixed;
while ((state = ippReadIO(&data, (ipp_iocb_t)read_cb, 1, NULL,
request)) != IPP_STATE_DATA)
if (state == IPP_STATE_ERROR)
break;
length = ippLength(request);
if (state != IPP_STATE_DATA)
{
printf("FAIL - %d bytes read.\n", (int)data.rpos);
status = 1;
}
else if (data.rpos != sizeof(mixed))
{
printf("FAIL - read %d bytes, expected %d bytes!\n", (int)data.rpos,
(int)sizeof(mixed));
print_attributes(request, 8);
status = 1;
}
else if (length != (sizeof(mixed) + 4))
{
printf("FAIL - wrong ippLength(), %d instead of %d bytes!\n",
(int)length, (int)sizeof(mixed) + 4);
print_attributes(request, 8);
status = 1;
}
else
puts("PASS");
fputs("ippFindAttribute(notify-lease-duration-supported): ", stdout);
if ((attr = ippFindAttribute(request, "notify-lease-duration-supported",
IPP_TAG_ZERO)) == NULL)
{
puts("FAIL (not found)");
status = 1;
}
else if (attr->value_tag != IPP_TAG_RANGE)
{
printf("FAIL (wrong type - %s)\n", ippTagString(attr->value_tag));
status = 1;
}
else if (attr->num_values != 2)
{
printf("FAIL (wrong count - %d)\n", attr->num_values);
status = 1;
}
else if (attr->values[0].range.lower != 1 ||
attr->values[0].range.upper != 1 ||
attr->values[1].range.lower != 16 ||
attr->values[1].range.upper != 32)
{
printf("FAIL (wrong values - %d,%d and %d,%d)\n",
attr->values[0].range.lower,
attr->values[0].range.upper,
attr->values[1].range.lower,
attr->values[1].range.upper);
status = 1;
}
else
puts("PASS");
ippDelete(request);
#ifdef DEBUG
/*
* Test that private option array is sorted...
*/
fputs("_ippCheckOptions: ", stdout);
if ((name = _ippCheckOptions()) == NULL)
puts("PASS");
else
{
printf("FAIL (\"%s\" out of order)\n", name);
status = 1;
}
#endif /* DEBUG */
/*
* Test _ippFindOption() private API...
*/
fputs("_ippFindOption(\"printer-type\"): ", stdout);
if (_ippFindOption("printer-type"))
puts("PASS");
else
{
puts("FAIL");
status = 1;
}
/*
* Summarize...
*/
putchar('\n');
if (status)
puts("Core IPP tests failed.");
else
puts("Core IPP tests passed.");
}
else
{
/*
* Read IPP files...
*/
for (i = 1; i < (size_t)argc; i ++)
{
if (strlen(argv[i]) > 5 && !strcmp(argv[i] + strlen(argv[i]) - 5, ".test"))
{
/*
* Read an ASCII IPP message...
*/
_ipp_vars_t v; /* IPP variables */
_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"))
{
/*
* 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);
}
}
}
return (status);
}
/*
* 'hex_dump()' - Produce a hex dump of a buffer.
*/
void
hex_dump(const char *title, /* I - Title */
ipp_uchar_t *buffer, /* I - Buffer to dump */
size_t bytes) /* I - Number of bytes */
{
size_t i, j; /* Looping vars */
int ch; /* Current ASCII char */
/*
* Show lines of 16 bytes at a time...
*/
printf(" %s:\n", title);
for (i = 0; i < bytes; i += 16)
{
/*
* Show the offset...
*/
printf(" %04x ", (unsigned)i);
/*
* Then up to 16 bytes in hex...
*/
for (j = 0; j < 16; j ++)
if ((i + j) < bytes)
printf(" %02x", buffer[i + j]);
else
printf(" ");
/*
* Then the ASCII representation of the bytes...
*/
putchar(' ');
putchar(' ');
for (j = 0; j < 16 && (i + j) < bytes; j ++)
{
ch = buffer[i + j] & 127;
if (ch < ' ' || ch == 127)
putchar('.');
else
putchar(ch);
}
putchar('\n');
}
}
/*
* 'print_attributes()' - Print the attributes in a request...
*/
void
print_attributes(ipp_t *ipp, /* I - IPP request */
int indent) /* I - Indentation */
{
ipp_tag_t group; /* Current group */
ipp_attribute_t *attr; /* Current attribute */
char buffer[2048]; /* Value string */
for (group = IPP_TAG_ZERO, attr = ipp->attrs; attr; attr = attr->next)
{
if (!attr->name && indent == 4)
{
group = IPP_TAG_ZERO;
putchar('\n');
continue;
}
if (group != attr->group_tag)
{
group = attr->group_tag;
printf("\n%*s%s:\n\n", indent - 4, "", ippTagString(group));
}
ippAttributeString(attr, buffer, sizeof(buffer));
printf("%*s%s (%s%s): %s\n", indent, "", attr->name ? attr->name : "(null)", attr->num_values > 1 ? "1setOf " : "", ippTagString(attr->value_tag), buffer);
}
}
/*
* 'read_cb()' - Read data from a buffer.
*/
ssize_t /* O - Number of bytes read */
read_cb(_ippdata_t *data, /* I - Data */
ipp_uchar_t *buffer, /* O - Buffer to read */
size_t bytes) /* I - Number of bytes to read */
{
size_t count; /* Number of bytes */
/*
* Copy bytes from the data buffer to the read buffer...
*/
if ((count = data->wsize - data->rpos) > bytes)
count = bytes;
memcpy(buffer, data->wbuffer + data->rpos, count);
data->rpos += count;
/*
* Return the number of bytes read...
*/
return ((ssize_t)count);
}
/*
* '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.
*/
ssize_t /* O - Number of bytes written */
write_cb(_ippdata_t *data, /* I - Data */
ipp_uchar_t *buffer, /* I - Buffer to write */
size_t bytes) /* I - Number of bytes to write */
{
size_t count; /* Number of bytes */
/*
* Loop until all bytes are written...
*/
if ((count = data->wsize - data->wused) > bytes)
count = bytes;
memcpy(data->wbuffer + data->wused, buffer, count);
data->wused += count;
/*
* Return the number of bytes written...
*/
return ((ssize_t)count);
}