ipp_attribute_t * ippAddRanges(ipp_t *ipp, ipp_tag_t group, const char *name, int num_values, const int *lower, const int *upper) { int i; ipp_attribute_t *attr; ipp_value_t *value; if (!ipp || !name || num_values < 1) return (NULL); if ((attr = _ippAddAttr(ipp, num_values)) == NULL) return (NULL); attr->name = stralloc(name); attr->group_tag = group; attr->value_tag = IPP_TAG_RANGE; if (lower != NULL && upper != NULL) for (i = 0, value = attr->values; i < num_values; i ++, value ++) { value->range.lower = lower[i]; value->range.upper = upper[i]; } return (attr); }
ipp_attribute_t * ippAddOctetString(ipp_t *ipp, ipp_tag_t group, const char *name, const void *data, int datalen) { ipp_attribute_t *attr; if (ipp == NULL || name == NULL) return (NULL); if ((attr = _ippAddAttr(ipp, 1)) == NULL) return (NULL); attr->name = stralloc(name); attr->group_tag = group; attr->value_tag = IPP_TAG_STRING; attr->values[0].unknown.length = datalen; if (data) { if ((attr->values[0].unknown.data = malloc(datalen)) == NULL) { ippDeleteAttribute(ipp, attr); return (NULL); } memcpy(attr->values[0].unknown.data, data, datalen); } return (attr); }
ipp_attribute_t * ippAddResolutions(ipp_t *ipp, ipp_tag_t group, const char *name, int num_values, ipp_res_t units, const int *xres, const int *yres) { int i; ipp_attribute_t *attr; ipp_value_t *value; if (!ipp || !name || num_values < 1) return (NULL); if ((attr = _ippAddAttr(ipp, num_values)) == NULL) return (NULL); attr->name = stralloc(name); attr->group_tag = group; attr->value_tag = IPP_TAG_RESOLUTION; if (xres != NULL && yres != NULL) for (i = 0, value = attr->values; i < num_values; i ++, value ++) { value->resolution.xres = xres[i]; value->resolution.yres = yres[i]; value->resolution.units = units; } return (attr); }
ipp_attribute_t * ippAddCollections( ipp_t *ipp, ipp_tag_t group, const char *name, int num_values, const ipp_t **values) { int i; ipp_attribute_t *attr; ipp_value_t *value; if (!ipp || !name || num_values < 1) return (NULL); if ((attr = _ippAddAttr(ipp, num_values)) == NULL) return (NULL); attr->name = stralloc(name); attr->group_tag = group; attr->value_tag = IPP_TAG_BEGIN_COLLECTION; if (values != NULL) { for (i = 0, value = attr->values; i < num_values; i ++, value ++) { value->collection = (ipp_t *)values[i]; value->collection->use ++; } } return (attr); }
ipp_attribute_t * ippAddIntegers(ipp_t *ipp, ipp_tag_t group, ipp_tag_t type, const char *name, int num_values, const int *values) { int i; ipp_attribute_t *attr; ipp_value_t *value; if (!ipp || !name || num_values < 1) return (NULL); if ((attr = _ippAddAttr(ipp, num_values)) == NULL) return (NULL); attr->name = stralloc(name); attr->group_tag = group; attr->value_tag = type; if (values != NULL) for (i = 0, value = attr->values; i < num_values; i ++, value ++) value->integer = values[i]; return (attr); }
ipp_attribute_t * ippAddResolution(ipp_t *ipp, ipp_tag_t group, const char *name, ipp_res_t units, int xres, int yres) { ipp_attribute_t *attr; if (!ipp || !name) return (NULL); if ((attr = _ippAddAttr(ipp, 1)) == NULL) return (NULL); attr->name = stralloc(name); attr->group_tag = group; attr->value_tag = IPP_TAG_RESOLUTION; attr->values[0].resolution.xres = xres; attr->values[0].resolution.yres = yres; attr->values[0].resolution.units = units; return (attr); }
ipp_attribute_t * ippAddBooleans(ipp_t *ipp, ipp_tag_t group, const char *name, int num_values, const char *values) { int i; ipp_attribute_t *attr; ipp_value_t *value; if (!ipp || !name || num_values < 1) return (NULL); if ((attr = _ippAddAttr(ipp, num_values)) == NULL) return (NULL); attr->name = stralloc(name); attr->group_tag = group; attr->value_tag = IPP_TAG_BOOLEAN; if (values != NULL) for (i = 0, value = attr->values; i < num_values; i ++, value ++) value->boolean = values[i]; return (attr); }
ipp_attribute_t * ippAddSeparator(ipp_t *ipp) { ipp_attribute_t *attr; if (!ipp) return (NULL); if ((attr = _ippAddAttr(ipp, 0)) == NULL) return (NULL); attr->group_tag = IPP_TAG_ZERO; attr->value_tag = IPP_TAG_ZERO; return (attr); }
ipp_attribute_t * ippAddString(ipp_t *ipp, ipp_tag_t group, ipp_tag_t type, const char *name, const char *charset, const char *value) { ipp_attribute_t *attr; char buffer[1024], *bufptr; if (!ipp || !name) return (NULL); if ((attr = _ippAddAttr(ipp, 1)) == NULL) return (NULL); if (type == IPP_TAG_LANGUAGE && !strcaseinsensitivecmp(value, "C")) value = "en"; if ((type == IPP_TAG_LANGUAGE || type == IPP_TAG_CHARSET) && value) { strncpy(buffer, value, sizeof(buffer)); value = buffer; for (bufptr = buffer; *bufptr; bufptr ++) if (*bufptr == '_') *bufptr = '-'; else *bufptr = tolower(*bufptr & 255); } attr->name = stralloc(name); attr->group_tag = group; attr->value_tag = type; attr->values[0].string.charset = ((int)type & IPP_TAG_COPY) ? (char *)charset : charset ? stralloc(charset) : NULL; attr->values[0].string.text = ((int)type & IPP_TAG_COPY) ? (char *)value : value ? stralloc(value) : NULL; return (attr); }
ipp_attribute_t * ippAddBoolean(ipp_t *ipp, ipp_tag_t group, const char *name, char value) { ipp_attribute_t *attr; if (!ipp || !name) return (NULL); if ((attr = _ippAddAttr(ipp, 1)) == NULL) return (NULL); attr->name = stralloc(name); attr->group_tag = group; attr->value_tag = IPP_TAG_BOOLEAN; attr->values[0].boolean = value; return (attr); }
ipp_attribute_t * ippAddDate(ipp_t *ipp, ipp_tag_t group, const char *name, const ipp_uchar_t *value) { ipp_attribute_t *attr; if (!ipp || !name || !value) return (NULL); if ((attr = _ippAddAttr(ipp, 1)) == NULL) return (NULL); attr->name = stralloc(name); attr->group_tag = group; attr->value_tag = IPP_TAG_DATE; memcpy(attr->values[0].date, value, 11); return (attr); }
ipp_attribute_t * ippAddInteger(ipp_t *ipp, ipp_tag_t group, ipp_tag_t type, const char *name, int value) { ipp_attribute_t *attr; if (!ipp || !name) return (NULL); if ((attr = _ippAddAttr(ipp, 1)) == NULL) return (NULL); attr->name = stralloc(name); attr->group_tag = group; attr->value_tag = type; attr->values[0].integer = value; return (attr); }
ipp_attribute_t * ippAddCollection(ipp_t *ipp, ipp_tag_t group, const char *name, ipp_t *value) { ipp_attribute_t *attr; if (!ipp || !name) return (NULL); if ((attr = _ippAddAttr(ipp, 1)) == NULL) return (NULL); attr->name = stralloc(name); attr->group_tag = group; attr->value_tag = IPP_TAG_BEGIN_COLLECTION; attr->values[0].collection = value; value->use ++; return (attr); }
ipp_attribute_t * ippAddRange(ipp_t *ipp, ipp_tag_t group, const char *name, int lower, int upper) { ipp_attribute_t *attr; if (!ipp || !name) return (NULL); if ((attr = _ippAddAttr(ipp, 1)) == NULL) return (NULL); attr->name = stralloc(name); attr->group_tag = group; attr->value_tag = IPP_TAG_RANGE; attr->values[0].range.lower = lower; attr->values[0].range.upper = upper; return (attr); }
void cupsEncodeOptions2( ipp_t *ipp, /* I - Request to add to */ int num_options, /* I - Number of options */ cups_option_t *options, /* I - Options */ ipp_tag_t group_tag) /* I - Group to encode */ { int i, j; /* Looping vars */ int count; /* Number of values */ char *s, /* Pointer into option value */ *val, /* Pointer to option value */ *copy, /* Copy of option value */ *sep, /* Option separator */ quote; /* Quote character */ ipp_attribute_t *attr; /* IPP attribute */ ipp_tag_t value_tag; /* IPP value tag */ cups_option_t *option; /* Current option */ ipp_t *collection; /* Collection value */ int num_cols; /* Number of collection values */ cups_option_t *cols; /* Collection values */ DEBUG_printf(("cupsEncodeOptions2(ipp=%p, num_options=%d, options=%p, " "group_tag=%x)", ipp, num_options, options, group_tag)); /* * Range check input... */ if (!ipp || num_options < 1 || !options) return; /* * Do special handling for the document-format/raw options... */ if (group_tag == IPP_TAG_OPERATION) { /* * Handle the document format stuff first... */ if ((val = (char *)cupsGetOption("document-format", num_options, options)) != NULL) ippAddString(ipp, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format", NULL, val); else if (cupsGetOption("raw", num_options, options)) ippAddString(ipp, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format", NULL, "application/vnd.cups-raw"); else ippAddString(ipp, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format", NULL, "application/octet-stream"); } /* * Then loop through the options... */ for (i = num_options, option = options; i > 0; i --, option ++) { _ipp_option_t *match; /* Matching attribute */ /* * Skip document format options that are handled above... */ if (!_cups_strcasecmp(option->name, "raw") || !_cups_strcasecmp(option->name, "document-format") || !option->name[0]) continue; /* * Figure out the proper value and group tags for this option... */ if ((match = _ippFindOption(option->name)) != NULL) { if (match->group_tag != group_tag) continue; value_tag = match->value_tag; } else { int namelen; /* Length of name */ namelen = (int)strlen(option->name); if (namelen < 9 || strcmp(option->name + namelen - 8, "-default")) { if (group_tag != IPP_TAG_JOB) continue; } else if (group_tag != IPP_TAG_PRINTER) continue; if (!_cups_strcasecmp(option->value, "true") || !_cups_strcasecmp(option->value, "false")) value_tag = IPP_TAG_BOOLEAN; else value_tag = IPP_TAG_NAME; } /* * Count the number of values... */ if (match && match->multivalue) { for (count = 1, sep = option->value, quote = 0; *sep; sep ++) { if (*sep == quote) quote = 0; else if (!quote && (*sep == '\'' || *sep == '\"')) { /* * Skip quoted option value... */ quote = *sep++; } else if (*sep == ',' && !quote) count ++; else if (*sep == '\\' && sep[1]) sep ++; } } else count = 1; DEBUG_printf(("2cupsEncodeOptions2: option=\"%s\", count=%d", option->name, count)); /* * Allocate memory for the attribute values... */ if ((attr = _ippAddAttr(ipp, count)) == NULL) { /* * Ran out of memory! */ DEBUG_puts("1cupsEncodeOptions2: Ran out of memory for attributes!"); return; } /* * Now figure out what type of value we have... */ attr->group_tag = group_tag; attr->value_tag = value_tag; /* * Copy the name over... */ attr->name = _cupsStrAlloc(option->name); if (count > 1) { /* * Make a copy of the value we can fiddle with... */ if ((copy = strdup(option->value)) == NULL) { /* * Ran out of memory! */ DEBUG_puts("1cupsEncodeOptions2: Ran out of memory for value copy!"); ippDeleteAttribute(ipp, attr); return; } val = copy; } else { /* * Since we have a single value, use the value directly... */ val = option->value; copy = NULL; } /* * Scan the value string for values... */ for (j = 0, sep = val; j < count; val = sep, j ++) { /* * Find the end of this value and mark it if needed... */ if (count > 1) { for (quote = 0; *sep; sep ++) { if (*sep == quote) { /* * Finish quoted value... */ quote = 0; } else if (!quote && (*sep == '\'' || *sep == '\"')) { /* * Handle quoted option value... */ quote = *sep; } else if (*sep == ',' && count > 1) break; else if (*sep == '\\' && sep[1]) { /* * Skip quoted character... */ sep ++; } } if (*sep == ',') *sep++ = '\0'; } /* * Copy the option value(s) over as needed by the type... */ switch (attr->value_tag) { case IPP_TAG_INTEGER : case IPP_TAG_ENUM : /* * Integer/enumeration value... */ attr->values[j].integer = strtol(val, &s, 10); DEBUG_printf(("2cupsEncodeOptions2: Added integer option value " "%d...", attr->values[j].integer)); break; case IPP_TAG_BOOLEAN : if (!_cups_strcasecmp(val, "true") || !_cups_strcasecmp(val, "on") || !_cups_strcasecmp(val, "yes")) { /* * Boolean value - true... */ attr->values[j].boolean = 1; DEBUG_puts("2cupsEncodeOptions2: Added boolean true value..."); } else { /* * Boolean value - false... */ attr->values[j].boolean = 0; DEBUG_puts("2cupsEncodeOptions2: Added boolean false value..."); } break; case IPP_TAG_RANGE : /* * Range... */ if (*val == '-') { attr->values[j].range.lower = 1; s = val; } else attr->values[j].range.lower = strtol(val, &s, 10); if (*s == '-') { if (s[1]) attr->values[j].range.upper = strtol(s + 1, NULL, 10); else attr->values[j].range.upper = 2147483647; } else attr->values[j].range.upper = attr->values[j].range.lower; DEBUG_printf(("2cupsEncodeOptions2: Added range option value " "%d-%d...", attr->values[j].range.lower, attr->values[j].range.upper)); break; case IPP_TAG_RESOLUTION : /* * Resolution... */ attr->values[j].resolution.xres = strtol(val, &s, 10); if (*s == 'x') attr->values[j].resolution.yres = strtol(s + 1, &s, 10); else attr->values[j].resolution.yres = attr->values[j].resolution.xres; if (!_cups_strcasecmp(s, "dpc")) attr->values[j].resolution.units = IPP_RES_PER_CM; else attr->values[j].resolution.units = IPP_RES_PER_INCH; DEBUG_printf(("2cupsEncodeOptions2: Added resolution option value " "%s...", val)); break; case IPP_TAG_STRING : /* * octet-string */ attr->values[j].unknown.length = (int)strlen(val); attr->values[j].unknown.data = strdup(val); DEBUG_printf(("2cupsEncodeOptions2: Added octet-string value " "\"%s\"...", (char *)attr->values[j].unknown.data)); break; case IPP_TAG_BEGIN_COLLECTION : /* * Collection value */ num_cols = cupsParseOptions(val, 0, &cols); if ((collection = ippNew()) == NULL) { cupsFreeOptions(num_cols, cols); if (copy) free(copy); ippDeleteAttribute(ipp, attr); return; } attr->values[j].collection = collection; cupsEncodeOptions2(collection, num_cols, cols, IPP_TAG_JOB); cupsFreeOptions(num_cols, cols); break; default : if ((attr->values[j].string.text = _cupsStrAlloc(val)) == NULL) { /* * Ran out of memory! */ DEBUG_puts("1cupsEncodeOptions2: Ran out of memory for string!"); if (copy) free(copy); ippDeleteAttribute(ipp, attr); return; } DEBUG_printf(("2cupsEncodeOptions2: Added string value \"%s\"...", val)); break; } } if (copy) free(copy); } }
ipp_attribute_t * ippAddStrings( ipp_t *ipp, ipp_tag_t group, ipp_tag_t type, const char *name, int num_values, const char *charset, const char * const *values) { int i; ipp_attribute_t *attr; ipp_value_t *value; char buffer[1024], *bufptr; if (!ipp || !name || num_values < 1) return (NULL); if ((attr = _ippAddAttr(ipp, num_values)) == NULL) return (NULL); attr->name = stralloc(name); attr->group_tag = group; attr->value_tag = type; for (i = 0, value = attr->values; i < num_values; i ++, value ++) { if (i == 0) value->string.charset = ((int)type & IPP_TAG_COPY) ? (char *)charset : charset ? stralloc(charset) : NULL; else value->string.charset = attr->values[0].string.charset; if (values != NULL) { if ((int)type & IPP_TAG_COPY) value->string.text = (char *)values[i]; else if (type == IPP_TAG_LANGUAGE && !strcaseinsensitivecmp(values[i], "C")) { value->string.text = ((int)type & IPP_TAG_COPY) ? "en" : "en"; } else if (type == IPP_TAG_LANGUAGE || type == IPP_TAG_CHARSET) { strncpy(buffer, values[i], sizeof(buffer)); for (bufptr = buffer; *bufptr; bufptr ++) if (*bufptr == '_') *bufptr = '-'; else *bufptr = tolower(*bufptr & 255); value->string.text = stralloc(buffer); } else value->string.text = stralloc(values[i]); } } return (attr); }
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); }