ipp_state_t ippRead(http_t *http, ipp_t *ipp) { if (!http) return (IPP_ERROR); return (ippReadIO(http, (ipp_iocb_t)ipp_read_http, http->blocking, NULL, ipp)); }
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 mixed data and confirm we converted everything to rangeOfInteger * values... */ printf("Read Mixed integer/rangeOfInteger from Memory: "); 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 ((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\"!\n", argv[i]); status = 1; } else { printf("\n%s:\n", argv[i]); print_attributes(request, 4); } ippDelete(request); cupsFileClose(fp); } } return (status); }
ipp_state_t ippReadIO(void *src, ipp_iocb_t cb, int blocking, ipp_t *parent, ipp_t *ipp) { int n; unsigned char *buffer, string[IPP_MAX_NAME], *bufptr; ipp_attribute_t *attr; ipp_tag_t tag; ipp_tag_t value_tag; ipp_value_t *value; if (!src || !ipp) return (IPP_ERROR); if ((buffer = ipp_buffer_get()) == NULL) { return (IPP_ERROR); } switch (ipp->state) { case IPP_IDLE : ipp->state = (ipp_state_t)(ipp->state+1); case IPP_HEADER : if (parent == NULL) { if ((*cb)(src, buffer, 8) < 8) { ipp_buffer_release(buffer); return (IPP_ERROR); } ipp->request.any.version[0] = buffer[0]; ipp->request.any.version[1] = buffer[1]; ipp->request.any.op_status = (buffer[2] << 8) | buffer[3]; ipp->request.any.request_id = (((((buffer[4] << 8) | buffer[5]) << 8) | buffer[6]) << 8) | buffer[7]; } ipp->state = IPP_ATTRIBUTE; ipp->current = NULL; ipp->curtag = IPP_TAG_ZERO; ipp->prev = ipp->last; if (!blocking) break; case IPP_ATTRIBUTE : for (;;) { if ((*cb)(src, buffer, 1) < 1) { ipp_buffer_release(buffer); return (IPP_ERROR); } tag = (ipp_tag_t)buffer[0]; if (tag == IPP_TAG_END) { ipp->state = IPP_DATA; break; } else if (tag < IPP_TAG_UNSUPPORTED_VALUE) { if (ipp->curtag == tag) ipp->prev = ippAddSeparator(ipp); else if (ipp->current) ipp->prev = ipp->current; ipp->curtag = tag; ipp->current = NULL; continue; } if ((*cb)(src, buffer, 2) < 2) { ipp_buffer_release(buffer); return (IPP_ERROR); } n = (buffer[0] << 8) | buffer[1]; if (n >= IPP_BUF_SIZE) { ipp_buffer_release(buffer); return (IPP_ERROR); } if (n == 0 && tag != IPP_TAG_MEMBERNAME && tag != IPP_TAG_END_COLLECTION) { if (ipp->current == NULL) { ipp_buffer_release(buffer); return (IPP_ERROR); } attr = ipp->current; value_tag = (ipp_tag_t)(attr->value_tag & IPP_TAG_MASK); if (value_tag == IPP_TAG_ZERO) { attr->value_tag = tag; } else if (value_tag == IPP_TAG_TEXTLANG || value_tag == IPP_TAG_NAMELANG || (value_tag >= IPP_TAG_TEXT && value_tag <= IPP_TAG_MIMETYPE)) { if (tag != IPP_TAG_TEXTLANG && tag != IPP_TAG_NAMELANG && (tag < IPP_TAG_TEXT || tag > IPP_TAG_MIMETYPE) && tag != IPP_TAG_NOVALUE) { ipp_buffer_release(buffer); return (IPP_ERROR); } } else if (value_tag != tag) { ipp_buffer_release(buffer); return (IPP_ERROR); } if (attr->num_values == 1 || (attr->num_values > 0 && (attr->num_values & (IPP_MAX_VALUES - 1)) == 0)) { ipp_attribute_t *temp; if ((temp = (ipp_attribute_t *)realloc(attr, sizeof(ipp_attribute_t) + (attr->num_values + IPP_MAX_VALUES - 1) * sizeof(ipp_value_t))) == NULL) { ipp_buffer_release(buffer); return (IPP_ERROR); } if (temp != attr) { if (ipp->prev) ipp->prev->next = temp; else ipp->attrs = temp; attr = ipp->current = ipp->last = temp; } } } else if (tag == IPP_TAG_MEMBERNAME) { if (n) { ipp_buffer_release(buffer); return (IPP_ERROR); } if (ipp->current) ipp->prev = ipp->current; attr = ipp->current = _ippAddAttr(ipp, 1); attr->group_tag = ipp->curtag; attr->value_tag = IPP_TAG_ZERO; attr->num_values = 0; } else if (tag != IPP_TAG_END_COLLECTION) { if ((*cb)(src, buffer, n) < n) { ipp_buffer_release(buffer); return (IPP_ERROR); } buffer[n] = '\0'; if (ipp->current) ipp->prev = ipp->current; if ((attr = ipp->current = _ippAddAttr(ipp, 1)) == NULL) { ipp_buffer_release(buffer); return (IPP_ERROR); } attr->group_tag = ipp->curtag; attr->value_tag = tag; attr->name = stralloc((char *)buffer); attr->num_values = 0; } else attr = NULL; if (tag != IPP_TAG_END_COLLECTION) value = attr->values + attr->num_values; else value = NULL; if ((*cb)(src, buffer, 2) < 2) { ipp_buffer_release(buffer); return (IPP_ERROR); } n = (buffer[0] << 8) | buffer[1]; switch (tag) { case IPP_TAG_INTEGER : case IPP_TAG_ENUM : if (n != 4) { ipp_buffer_release(buffer); return (IPP_ERROR); } if ((*cb)(src, buffer, 4) < 4) { ipp_buffer_release(buffer); return (IPP_ERROR); } n = (((((buffer[0] << 8) | buffer[1]) << 8) | buffer[2]) << 8) | buffer[3]; value->integer = n; break; case IPP_TAG_BOOLEAN : if (n != 1) { ipp_buffer_release(buffer); return (IPP_ERROR); } if ((*cb)(src, buffer, 1) < 1) { ipp_buffer_release(buffer); return (IPP_ERROR); } value->boolean = buffer[0]; break; case IPP_TAG_NOVALUE : case IPP_TAG_NOTSETTABLE : case IPP_TAG_DELETEATTR : case IPP_TAG_ADMINDEFINE : if (attr->value_tag == tag) { if (n == 0) break; attr->value_tag = IPP_TAG_TEXT; } 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 : if (n >= IPP_BUF_SIZE) { ipp_buffer_release(buffer); return (IPP_ERROR); } if ((*cb)(src, buffer, n) < n) { ipp_buffer_release(buffer); return (IPP_ERROR); } buffer[n] = '\0'; value->string.text = stralloc((char *)buffer); break; case IPP_TAG_DATE : if (n != 11) { ipp_buffer_release(buffer); return (IPP_ERROR); } if ((*cb)(src, value->date, 11) < 11) { ipp_buffer_release(buffer); return (IPP_ERROR); } break; case IPP_TAG_RESOLUTION : if (n != 9) { ipp_buffer_release(buffer); return (IPP_ERROR); } if ((*cb)(src, buffer, 9) < 9) { ipp_buffer_release(buffer); return (IPP_ERROR); } value->resolution.xres = (((((buffer[0] << 8) | buffer[1]) << 8) | buffer[2]) << 8) | buffer[3]; value->resolution.yres = (((((buffer[4] << 8) | buffer[5]) << 8) | buffer[6]) << 8) | buffer[7]; value->resolution.units = (ipp_res_t)buffer[8]; break; case IPP_TAG_RANGE : if (n != 8) { ipp_buffer_release(buffer); return (IPP_ERROR); } if ((*cb)(src, buffer, 8) < 8) { ipp_buffer_release(buffer); return (IPP_ERROR); } value->range.lower = (((((buffer[0] << 8) | buffer[1]) << 8) | buffer[2]) << 8) | buffer[3]; value->range.upper = (((((buffer[4] << 8) | buffer[5]) << 8) | buffer[6]) << 8) | buffer[7]; break; case IPP_TAG_TEXTLANG : case IPP_TAG_NAMELANG : if (n >= IPP_BUF_SIZE || n < 4) { ipp_buffer_release(buffer); return (IPP_ERROR); } if ((*cb)(src, buffer, n) < n) { ipp_buffer_release(buffer); return (IPP_ERROR); } bufptr = buffer; n = (bufptr[0] << 8) | bufptr[1]; if ((bufptr + 2 + n) >= (buffer + IPP_BUF_SIZE) || n >= sizeof(string)) { ipp_buffer_release(buffer); return (IPP_ERROR); } memcpy(string, bufptr + 2, n); string[n] = '\0'; value->string.charset = stralloc((char *)string); bufptr += 2 + n; n = (bufptr[0] << 8) | bufptr[1]; if ((bufptr + 2 + n) >= (buffer + IPP_BUF_SIZE)) { ipp_buffer_release(buffer); return (IPP_ERROR); } bufptr[2 + n] = '\0'; value->string.text = stralloc((char *)bufptr + 2); break; case IPP_TAG_BEGIN_COLLECTION : value->collection = ippNew(); if (n > 0) { ipp_buffer_release(buffer); return (IPP_ERROR); } if (ippReadIO(src, cb, 1, ipp, value->collection) == IPP_ERROR) { ipp_buffer_release(buffer); return (IPP_ERROR); } break; case IPP_TAG_END_COLLECTION : ipp_buffer_release(buffer); if (n > 0) { return (IPP_ERROR); } return (ipp->state = IPP_DATA); case IPP_TAG_MEMBERNAME : if (n >= IPP_BUF_SIZE) { ipp_buffer_release(buffer); return (IPP_ERROR); } if ((*cb)(src, buffer, n) < n) { ipp_buffer_release(buffer); return (IPP_ERROR); } buffer[n] = '\0'; attr->name = stralloc((char *)buffer); attr->num_values --; break; default : if (n > IPP_MAX_LENGTH) { ipp_buffer_release(buffer); return (IPP_ERROR); } if (!value) { ipp_buffer_release(buffer); return (IPP_ERROR); } value->unknown.length = n; if (n > 0) { if ((value->unknown.data = malloc(n)) == NULL) { ipp_buffer_release(buffer); return (IPP_ERROR); } if ((*cb)(src,(ipp_uchar_t *)value->unknown.data, n) < n) { ipp_buffer_release(buffer); return (IPP_ERROR); } } else value->unknown.data = NULL; break; } attr->num_values ++; if (!blocking) break; } break; case IPP_DATA : break; default : break; } ipp_buffer_release(buffer); return (ipp->state); }
ipp_state_t ippReadFile(int fd, ipp_t *ipp) { return (ippReadIO(&fd, (ipp_iocb_t)ipp_read_file, 1, NULL, ipp)); }