* Local functions...
*/
+static unsigned char *ipp_buffer_get(void);
+static void ipp_buffer_release(unsigned char *b);
static size_t ipp_length(ipp_t *ipp, int collection);
static ssize_t ipp_read_http(http_t *http, ipp_uchar_t *buffer,
size_t length);
ipp_t *ipp) /* I - IPP data */
{
int n; /* Length of data */
- unsigned char buffer[IPP_MAX_LENGTH + 1],
- /* Data buffer */
+ unsigned char *buffer, /* Data buffer */
string[IPP_MAX_NAME],
/* Small string buffer */
*bufptr; /* Pointer into buffer */
if (!src || !ipp)
return (IPP_ERROR);
+ if ((buffer = ipp_buffer_get()) == NULL)
+ {
+ DEBUG_puts("ippReadIO: Unable to get read buffer!");
+ return (IPP_ERROR);
+ }
+
switch (ipp->state)
{
case IPP_IDLE :
if ((*cb)(src, buffer, 8) < 8)
{
DEBUG_puts("ippReadIO: Unable to read header!");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
{
DEBUG_printf(("ippReadIO: version number (%d.%d) is bad.\n",
buffer[0], buffer[1]));
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
for (;;)
{
if ((*cb)(src, buffer, 1) < 1)
+ {
+ DEBUG_puts("ippReadIO: Callback returned EOF/error");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
+ }
DEBUG_printf(("ippReadIO: ipp->current=%p, ipp->prev=%p\n",
ipp->current, ipp->prev));
if ((*cb)(src, buffer, 2) < 2)
{
DEBUG_puts("ippReadIO: unable to read name length!");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
n = (buffer[0] << 8) | buffer[1];
- if (n > (sizeof(buffer) - 1))
+ if (n >= IPP_BUF_SIZE)
{
DEBUG_printf(("ippReadIO: bad name length %d!\n", n));
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
*/
if (ipp->current == NULL)
+ {
+ DEBUG_puts("ippReadIO: Attribute without name and no current");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
+ }
attr = ipp->current;
value_tag = (ipp_tag_t)(attr->value_tag & IPP_TAG_MASK);
DEBUG_printf(("ippReadIO: 1setOf value tag %x(%s) != %x(%s)\n",
value_tag, ippTagString(value_tag), tag,
ippTagString(tag)));
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
}
DEBUG_printf(("ippReadIO: value tag %x(%s) != %x(%s)\n",
value_tag, ippTagString(value_tag), tag,
ippTagString(tag)));
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
if ((temp = realloc(attr, sizeof(ipp_attribute_t) +
(attr->num_values + IPP_MAX_VALUES - 1) *
sizeof(ipp_value_t))) == NULL)
+ {
+ DEBUG_puts("ippReadIO: Unable to resize attribute");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
+ }
if (temp != attr)
{
if (n)
{
DEBUG_puts("ippReadIO: member name not empty!");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
if ((*cb)(src, buffer, n) < n)
{
DEBUG_puts("ippReadIO: unable to read name!");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
if ((attr = ipp->current = _ippAddAttr(ipp, 1)) == NULL)
{
DEBUG_puts("ippReadIO: unable to allocate attribute!");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
if ((*cb)(src, buffer, 2) < 2)
{
DEBUG_puts("ippReadIO: unable to read value length!");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
if (n != 4)
{
DEBUG_printf(("ippReadIO: bad value length %d!\n", n));
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
if ((*cb)(src, buffer, 4) < 4)
{
DEBUG_puts("ippReadIO: Unable to read integer value!");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
if (n != 1)
{
DEBUG_printf(("ippReadIO: bad value length %d!\n", n));
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
if ((*cb)(src, buffer, 1) < 1)
{
DEBUG_puts("ippReadIO: Unable to read boolean value!");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
case IPP_TAG_CHARSET :
case IPP_TAG_LANGUAGE :
case IPP_TAG_MIMETYPE :
- if (n >= sizeof(buffer))
+ if (n >= IPP_BUF_SIZE)
{
DEBUG_printf(("ippReadIO: bad value length %d!\n", n));
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
if ((*cb)(src, buffer, n) < n)
{
DEBUG_puts("ippReadIO: unable to read name!");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
if (n != 11)
{
DEBUG_printf(("ippReadIO: bad value length %d!\n", n));
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
if ((*cb)(src, value->date, 11) < 11)
{
DEBUG_puts("ippReadIO: Unable to date integer value!");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
break;
if (n != 9)
{
DEBUG_printf(("ippReadIO: bad value length %d!\n", n));
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
if ((*cb)(src, buffer, 9) < 9)
{
DEBUG_puts("ippReadIO: Unable to read resolution value!");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
if (n != 8)
{
DEBUG_printf(("ippReadIO: bad value length %d!\n", n));
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
if ((*cb)(src, buffer, 8) < 8)
{
DEBUG_puts("ippReadIO: Unable to read range value!");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
case IPP_TAG_TEXTLANG :
case IPP_TAG_NAMELANG :
- if (n >= sizeof(buffer) || n < 4)
+ if (n >= IPP_BUF_SIZE || n < 4)
{
DEBUG_printf(("ippReadIO: bad value length %d!\n", n));
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
if ((*cb)(src, buffer, n) < n)
{
DEBUG_puts("ippReadIO: Unable to read string w/language value!");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
n = (bufptr[0] << 8) | bufptr[1];
- if ((bufptr + 2 + n) >= (buffer + sizeof(buffer)) ||
+ if ((bufptr + 2 + n) >= (buffer + IPP_BUF_SIZE) ||
n >= sizeof(string))
{
DEBUG_printf(("ippReadIO: bad value length %d!\n", n));
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
bufptr += 2 + n;
n = (bufptr[0] << 8) | bufptr[1];
- if ((bufptr + 2 + n) >= (buffer + sizeof(buffer)))
+ if ((bufptr + 2 + n) >= (buffer + IPP_BUF_SIZE))
{
DEBUG_printf(("ippReadIO: bad value length %d!\n", n));
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
{
DEBUG_puts("ippReadIO: begCollection tag with value length "
"> 0!");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
if (ippReadIO(src, cb, 1, ipp, value->collection) == IPP_ERROR)
{
DEBUG_puts("ippReadIO: Unable to read collection value!");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
break;
case IPP_TAG_END_COLLECTION :
+ ipp_buffer_release(buffer);
+
if (n > 0)
{
DEBUG_puts("ippReadIO: endCollection tag with value length "
}
DEBUG_puts("ippReadIO: endCollection tag...");
-
return (ipp->state = IPP_DATA);
case IPP_TAG_MEMBERNAME :
* we need to carry over...
*/
- if (n >= sizeof(buffer))
+ if (n >= IPP_BUF_SIZE)
{
DEBUG_printf(("ippReadIO: bad value length %d!\n", n));
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
if ((*cb)(src, buffer, n) < n)
{
DEBUG_puts("ippReadIO: Unable to read member name value!");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
if (n > IPP_MAX_LENGTH)
{
DEBUG_printf(("ippReadIO: bad value length %d!\n", n));
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
if (!value)
{
DEBUG_puts("ippReadIO: NULL value!");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
if ((value->unknown.data = malloc(n)) == NULL)
{
DEBUG_puts("ippReadIO: Unable to allocate value");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
if ((*cb)(src, value->unknown.data, n) < n)
{
DEBUG_puts("ippReadIO: Unable to read unsupported value!");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
}
}
DEBUG_printf(("ippReadIO: returning ipp->state=%d!\n", ipp->state));
+ ipp_buffer_release(buffer);
return (ipp->state);
}
{
int i; /* Looping var */
int n; /* Length of data */
- unsigned char buffer[IPP_MAX_LENGTH + 2],
- /* Data buffer + length bytes */
+ unsigned char *buffer, /* Data buffer */
*bufptr; /* Pointer into buffer */
ipp_attribute_t *attr; /* Current attribute */
ipp_value_t *value; /* Current value */
if (!dst || !ipp)
return (IPP_ERROR);
+ if ((buffer = ipp_buffer_get()) == NULL)
+ {
+ DEBUG_puts("ippWriteIO: Unable to get write buffer");
+ return (IPP_ERROR);
+ }
+
switch (ipp->state)
{
case IPP_IDLE :
if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
{
DEBUG_puts("ippWriteIO: Could not write IPP header...");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
}
* overflow the buffer...
*/
- if ((n = (int)strlen(attr->name)) > (sizeof(buffer) - 4))
+ if ((n = (int)strlen(attr->name)) > (IPP_BUF_SIZE - 4))
+ {
+ DEBUG_printf(("ippWriteIO: Attribute name too long (%d)\n", n));
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
+ }
/*
* Write the value tag, name length, and name string...
* overflow the buffer...
*/
- if ((n = (int)strlen(attr->name)) > (sizeof(buffer) - 7))
+ if ((n = (int)strlen(attr->name)) > (IPP_BUF_SIZE - 7))
+ {
+ DEBUG_printf(("ippWriteIO: Attribute name too long (%d)\n", n));
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
+ }
/*
* Write the member name tag, name length, name string, value tag,
i < attr->num_values;
i ++, value ++)
{
- if ((sizeof(buffer) - (bufptr - buffer)) < 9)
+ if ((IPP_BUF_SIZE - (bufptr - buffer)) < 9)
{
if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
{
DEBUG_puts("ippWriteIO: Could not write IPP "
"attribute...");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
i < attr->num_values;
i ++, value ++)
{
- if ((sizeof(buffer) - (bufptr - buffer)) < 6)
+ if ((IPP_BUF_SIZE - (bufptr - buffer)) < 6)
{
if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
{
DEBUG_puts("ippWriteIO: Could not write IPP "
"attribute...");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
ippTagString(attr->value_tag)));
DEBUG_printf(("ippWriteIO: writing name=0,\"\"\n"));
- if ((sizeof(buffer) - (bufptr - buffer)) < 3)
+ if ((IPP_BUF_SIZE - (bufptr - buffer)) < 3)
{
if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
{
DEBUG_puts("ippWriteIO: Could not write IPP "
"attribute...");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
else
n = 0;
- if (n > (sizeof(buffer) - 2))
+ if (n > (IPP_BUF_SIZE - 2))
+ {
+ DEBUG_printf(("ippWriteIO: String too long (%d)\n", n));
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
+ }
DEBUG_printf(("ippWriteIO: writing string=%d,\"%s\"\n", n,
value->string.text));
- if ((int)(sizeof(buffer) - (bufptr - buffer)) < (n + 2))
+ if ((int)(IPP_BUF_SIZE - (bufptr - buffer)) < (n + 2))
{
if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
{
DEBUG_puts("ippWriteIO: Could not write IPP "
"attribute...");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
i < attr->num_values;
i ++, value ++)
{
- if ((sizeof(buffer) - (bufptr - buffer)) < 16)
+ if ((IPP_BUF_SIZE - (bufptr - buffer)) < 16)
{
if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
{
DEBUG_puts("ippWriteIO: Could not write IPP "
"attribute...");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
i < attr->num_values;
i ++, value ++)
{
- if ((sizeof(buffer) - (bufptr - buffer)) < 14)
+ if ((IPP_BUF_SIZE - (bufptr - buffer)) < 14)
{
if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
{
DEBUG_puts("ippWriteIO: Could not write IPP "
"attribute...");
- return (IPP_ERROR);
+ ipp_buffer_release(buffer);
+ return (IPP_ERROR);
}
bufptr = buffer;
i < attr->num_values;
i ++, value ++)
{
- if ((sizeof(buffer) - (bufptr - buffer)) < 13)
+ if ((IPP_BUF_SIZE - (bufptr - buffer)) < 13)
{
if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
{
DEBUG_puts("ippWriteIO: Could not write IPP "
"attribute...");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
* values with a zero-length name...
*/
- if ((sizeof(buffer) - (bufptr - buffer)) < 3)
+ if ((IPP_BUF_SIZE - (bufptr - buffer)) < 3)
{
if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
{
DEBUG_puts("ippWriteIO: Could not write IPP "
"attribute...");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
if (value->string.text != NULL)
n += (int)strlen(value->string.text);
- if (n > (sizeof(buffer) - 2))
+ if (n > (IPP_BUF_SIZE - 2))
+ {
+ DEBUG_printf(("ippWriteIO: text/nameWithLanguage value "
+ "too long (%d)\n", n));
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
+ }
- if ((int)(sizeof(buffer) - (bufptr - buffer)) < (n + 2))
+ if ((int)(IPP_BUF_SIZE - (bufptr - buffer)) < (n + 2))
{
if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
{
DEBUG_puts("ippWriteIO: Could not write IPP "
"attribute...");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
* value...
*/
- if ((sizeof(buffer) - (bufptr - buffer)) < 5)
+ if ((IPP_BUF_SIZE - (bufptr - buffer)) < 5)
{
if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
{
DEBUG_puts("ippWriteIO: Could not write IPP "
"attribute...");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
{
DEBUG_puts("ippWriteIO: Could not write IPP "
"attribute...");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
value->collection->state = IPP_IDLE;
- if (ippWriteIO(dst, cb, 1, ipp, value->collection) == IPP_ERROR)
+ if (ippWriteIO(dst, cb, 1, ipp,
+ value->collection) == IPP_ERROR)
+ {
+ DEBUG_puts("ippWriteIO: Unable to write collection value");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
+ }
}
break;
* values with a zero-length name...
*/
- if ((sizeof(buffer) - (bufptr - buffer)) < 3)
+ if ((IPP_BUF_SIZE - (bufptr - buffer)) < 3)
{
if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
{
DEBUG_puts("ippWriteIO: Could not write IPP "
"attribute...");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
n = value->unknown.length;
- if (n > (sizeof(buffer) - 2))
+ if (n > (IPP_BUF_SIZE - 2))
+ {
+ DEBUG_printf(("ippWriteIO: Data length too long (%d)\n",
+ n));
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
+ }
- if ((int)(sizeof(buffer) - (bufptr - buffer)) < (n + 2))
+ if ((int)(IPP_BUF_SIZE - (bufptr - buffer)) < (n + 2))
{
if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
{
DEBUG_puts("ippWriteIO: Could not write IPP "
"attribute...");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
{
DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
if ((*cb)(dst, buffer, n) < 0)
{
DEBUG_puts("ippWriteIO: Could not write IPP end-tag...");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
break; /* anti-compiler-warning-code */
}
+ ipp_buffer_release(buffer);
+
return (ipp->state);
}
}
+/*
+ * 'ipp_buffer_get()' - Get a read/write buffer.
+ */
+
+static unsigned char * /* O - Buffer */
+ipp_buffer_get(void)
+{
+ _ipp_buffer_t *buffer; /* Current buffer */
+ _cups_globals_t *cg = _cupsGlobals();
+ /* Global data */
+
+
+ for (buffer = cg->ipp_buffers; buffer; buffer = buffer->next)
+ if (!buffer->used)
+ {
+ buffer->used = 1;
+ return (buffer->d);
+ }
+
+ if ((buffer = malloc(sizeof(_ipp_buffer_t))) == NULL)
+ return (NULL);
+
+ buffer->used = 1;
+ buffer->next = cg->ipp_buffers;
+ cg->ipp_buffers = buffer;
+
+ return (buffer->d);
+}
+
+
+/*
+ * 'ipp_buffer_release()' - Release a read/write buffer.
+ */
+
+static void
+ipp_buffer_release(unsigned char *b) /* I - Buffer to release */
+{
+ ((_ipp_buffer_t *)b)->used = 0;
+}
+
+
/*
* 'ipp_length()' - Compute the length of an IPP message or collection value.
*/