/*
- * "$Id: ipp.c 6234 2007-02-05 20:25:50Z mike $"
+ * "$Id: ipp.c 7847 2008-08-19 04:22:14Z mike $"
*
- * Internet Printing Protocol support functions for the Common UNIX
- * Printing System (CUPS).
+ * Internet Printing Protocol functions for CUPS.
*
+ * Copyright 2007-2010 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
- * property of Easy Software Products 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 missing or damaged please contact Easy Software Products
- * at:
- *
- * Attn: CUPS Licensing Information
- * Easy Software Products
- * 44141 Airport View Drive, Suite 204
- * Hollywood, Maryland 20636 USA
- *
- * Voice: (301) 373-9600
- * EMail: cups-info@cups.org
- * WWW: http://www.cups.org
+ * 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/".
*
* This file is subject to the Apple OS-Developed Software exception.
*
* Include necessary headers...
*/
-#include "http-private.h"
-#include "globals.h"
-#include "debug.h"
-#include <stdlib.h>
-#include <errno.h>
+#include "cups-private.h"
#ifdef WIN32
# include <io.h>
#endif /* WIN32 */
* 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_attribute_t *attr; /* New attribute */
- DEBUG_printf(("ippAddBoolean(%p, %02x, \'%s\', %d)\n", ipp, group, name, value));
+ DEBUG_printf(("ippAddBoolean(ipp=%p, group=%02x(%s), name=\"%s\", value=%d)",
+ ipp, group, ippTagString(group), name, value));
- if (ipp == NULL || name == NULL)
+ if (!ipp || !name)
return (NULL);
if ((attr = _ippAddAttr(ipp, 1)) == NULL)
ipp_value_t *value; /* Current value */
- DEBUG_printf(("ippAddBooleans(%p, %02x, \'%s\', %d, %p)\n", ipp,
- group, name, num_values, values));
+ DEBUG_printf(("ippAddBooleans(ipp=%p, group=%02x(%s), name=\"%s\", "
+ "num_values=%d, values=%p)", ipp, group, ippTagString(group),
+ name, num_values, values));
- if (ipp == NULL || name == NULL || num_values < 1)
+ if (!ipp || !name || num_values < 1)
return (NULL);
if ((attr = _ippAddAttr(ipp, num_values)) == NULL)
/*
* 'ippAddCollection()' - Add a collection value.
*
- * @since CUPS 1.1.19@
+ * @since CUPS 1.1.19/Mac OS X 10.3@
*/
ipp_attribute_t * /* O - New attribute */
ipp_attribute_t *attr; /* New attribute */
- DEBUG_printf(("ippAddCollection(%p, %02x, \'%s\', %p)\n", ipp, group, name,
- value));
+ DEBUG_printf(("ippAddCollection(ipp=%p, group=%02x(%s), name=\"%s\", "
+ "value=%p)", ipp, group, ippTagString(group), name, value));
- if (ipp == NULL || name == NULL)
+ if (!ipp || !name)
return (NULL);
if ((attr = _ippAddAttr(ipp, 1)) == NULL)
attr->value_tag = IPP_TAG_BEGIN_COLLECTION;
attr->values[0].collection = value;
+ value->use ++;
+
return (attr);
}
/*
* 'ippAddCollections()' - Add an array of collection values.
*
- * @since CUPS 1.1.19@
+ * @since CUPS 1.1.19/Mac OS X 10.3@
*/
ipp_attribute_t * /* O - New attribute */
ipp_value_t *value; /* Current value */
- DEBUG_printf(("ippAddCollections(%p, %02x, \'%s\', %d, %p)\n", ipp,
- group, name, num_values, values));
+ DEBUG_printf(("ippAddCollections(ipp=%p, group=%02x(%s), name=\"%s\", "
+ "num_values=%d, values=%p)", ipp, group, ippTagString(group),
+ name, num_values, values));
- if (ipp == NULL || name == NULL || num_values < 1)
+ if (!ipp || !name || num_values < 1)
return (NULL);
if ((attr = _ippAddAttr(ipp, num_values)) == NULL)
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 *attr; /* New attribute */
- DEBUG_printf(("ippAddDate(%p, %02x, \'%s\', %p)\n", ipp, group, name,
- value));
+ DEBUG_printf(("ippAddDate(ipp=%p, group=%02x(%s), name=\"%s\", value=%p)",
+ ipp, group, ippTagString(group), name, value));
- if (ipp == NULL || name == NULL || value == NULL)
+ if (!ipp || !name || !value)
return (NULL);
if ((attr = _ippAddAttr(ipp, 1)) == NULL)
ipp_attribute_t *attr; /* New attribute */
- DEBUG_printf(("ippAddInteger(%p, %d, \'%s\', %d)\n", ipp, group, name,
- value));
+ DEBUG_printf(("ippAddInteger(ipp=%p, group=%02x(%s), type=%02x(%s), "
+ "name=\"%s\", value=%d)", ipp, group, ippTagString(group),
+ type, ippTagString(type), name, value));
- if (ipp == NULL || name == NULL)
+ if (!ipp || !name)
return (NULL);
if ((attr = _ippAddAttr(ipp, 1)) == NULL)
ipp_value_t *value; /* Current value */
- if (ipp == NULL || name == NULL || num_values < 1)
+ DEBUG_printf(("ippAddIntegers(ipp=%p, group=%02x(%s), type=%02x(%s), "
+ "name=\"%s\", num_values=%d, values=%p)", ipp,
+ group, ippTagString(group), type, ippTagString(type), name,
+ num_values, values));
+
+ if (!ipp || !name || num_values < 1)
return (NULL);
if ((attr = _ippAddAttr(ipp, num_values)) == NULL)
/*
* 'ippAddOctetString()' - Add an octetString value to an IPP message.
*
- * @since CUPS 1.2@
+ * @since CUPS 1.2/Mac OS X 10.5@
*/
ipp_attribute_t * /* O - New attribute */
if (data)
{
- attr->values[0].unknown.data = malloc(datalen);
+ if ((attr->values[0].unknown.data = malloc(datalen)) == NULL)
+ {
+ ippDeleteAttribute(ipp, attr);
+ return (NULL);
+ }
+
memcpy(attr->values[0].unknown.data, data, datalen);
}
*bufptr; /* Pointer into buffer */
- if (ipp == NULL || name == NULL)
+ DEBUG_printf(("ippAddString(ipp=%p, group=%02x(%s), type=%02x(%s), "
+ "name=\"%s\", charset=\"%s\", value=\"%s\")", ipp,
+ group, ippTagString(group), type, ippTagString(type), name,
+ charset, value));
+
+ if (!ipp || !name)
return (NULL);
if ((attr = _ippAddAttr(ipp, 1)) == NULL)
value = "en";
/*
- * Convert language values to lowercase and change _ to - as needed...
+ * Convert language and charset values to lowercase and change _ to - as
+ * needed...
*/
if ((type == IPP_TAG_LANGUAGE || type == IPP_TAG_CHARSET) && value)
int i; /* Looping var */
ipp_attribute_t *attr; /* New attribute */
ipp_value_t *value; /* Current value */
+ char buffer[1024], /* Language/charset value buffer */
+ *bufptr; /* Pointer into buffer */
- if (ipp == NULL || name == NULL || num_values < 1)
+ DEBUG_printf(("ippAddStrings(ipp=%p, group=%02x(%s), type=%02x(%s), "
+ "name=\"%s\", num_values=%d, charset=\"%s\", values=%p)", ipp,
+ group, ippTagString(group), type, ippTagString(type), name,
+ num_values, charset, values));
+
+ if (!ipp || !name || num_values < 1)
return (NULL);
if ((attr = _ippAddAttr(ipp, num_values)) == NULL)
if (values != NULL)
{
- /*
- * Force language to be English for the POSIX locale...
- */
+ if ((int)type & IPP_TAG_COPY)
+ value->string.text = (char *)values[i];
+ else if (type == IPP_TAG_LANGUAGE && !strcasecmp(values[i], "C"))
+ {
+ /*
+ * Force language to be English for the POSIX locale...
+ */
- if (type == IPP_TAG_LANGUAGE && !strcasecmp(values[i], "C"))
value->string.text = ((int)type & IPP_TAG_COPY) ? "en" :
_cupsStrAlloc("en");
+ }
+ else if (type == IPP_TAG_LANGUAGE || type == IPP_TAG_CHARSET)
+ {
+ /*
+ * Convert language values to lowercase and change _ to - as needed...
+ */
+
+ strlcpy(buffer, values[i], sizeof(buffer));
+
+ for (bufptr = buffer; *bufptr; bufptr ++)
+ if (*bufptr == '_')
+ *bufptr = '-';
+ else
+ *bufptr = tolower(*bufptr & 255);
+
+ value->string.text = _cupsStrAlloc(buffer);
+ }
else
- value->string.text = ((int)type & IPP_TAG_COPY) ? (char *)values[i] :
- _cupsStrAlloc(values[i]);
+ value->string.text = _cupsStrAlloc(values[i]);
+
}
}
ipp_attribute_t *attr; /* New attribute */
- if (ipp == NULL || name == NULL)
+ DEBUG_printf(("ippAddRange(ipp=%p, group=%02x(%s), name=\"%s\", lower=%d, "
+ "upper=%d)", ipp, group, ippTagString(group), name, lower,
+ upper));
+
+ if (!ipp || !name)
return (NULL);
if ((attr = _ippAddAttr(ipp, 1)) == NULL)
ipp_value_t *value; /* Current value */
- if (ipp == NULL || name == NULL || num_values < 1)
+ DEBUG_printf(("ippAddRanges(ipp=%p, group=%02x(%s), name=\"%s\", "
+ "num_values=%d, lower=%p, upper=%p)", ipp, group,
+ ippTagString(group), name, num_values, lower, upper));
+
+ if (!ipp || !name || num_values < 1)
return (NULL);
if ((attr = _ippAddAttr(ipp, num_values)) == NULL)
ipp_attribute_t *attr; /* New attribute */
- if (ipp == NULL || name == NULL)
+ DEBUG_printf(("ippAddResolution(ipp=%p, group=%02x(%s), name=\"%s\", "
+ "units=%d, xres=%d, yres=%d)", ipp, group,
+ ippTagString(group), name, units, xres, yres));
+
+ if (!ipp || !name)
return (NULL);
if ((attr = _ippAddAttr(ipp, 1)) == NULL)
ipp_value_t *value; /* Current value */
- if (ipp == NULL || name == NULL || num_values < 1)
+ DEBUG_printf(("ippAddResolutions(ipp=%p, group=%02x(%s), name=\"%s\", "
+ "num_value=%d, units=%d, xres=%p, yres=%p)", ipp, group,
+ ippTagString(group), name, num_values, units, xres, yres));
+
+ if (!ipp || !name || num_values < 1)
return (NULL);
if ((attr = _ippAddAttr(ipp, num_values)) == NULL)
ipp_attribute_t *attr; /* New attribute */
- DEBUG_printf(("ippAddSeparator(%p)\n", ipp));
+ DEBUG_printf(("ippAddSeparator(ipp=%p)", ipp));
- if (ipp == NULL)
+ if (!ipp)
return (NULL);
if ((attr = _ippAddAttr(ipp, 0)) == NULL)
time_t t; /* Computed time */
+ if (!date)
+ return (0);
+
memset(&unixdate, 0, sizeof(unixdate));
/*
*next; /* Next attribute */
- DEBUG_printf(("ippDelete(): %p\n", ipp));
+ DEBUG_printf(("ippDelete(ipp=%p)", ipp));
- if (ipp == NULL)
+ if (!ipp)
+ return;
+
+ ipp->use --;
+ if (ipp->use > 0)
return;
for (attr = ipp->attrs; attr != NULL; attr = next)
/*
* 'ippDeleteAttribute()' - Delete a single attribute in an IPP message.
*
- * @since CUPS 1.1.19@
+ * @since CUPS 1.1.19/Mac OS X 10.3@
*/
void
*prev; /* Previous attribute */
+ DEBUG_printf(("ippDeleteAttribute(ipp=%p, attr=%p(%s))", ipp, attr,
+ attr ? attr->name : "(null)"));
+
/*
* Find the attribute in the list...
*/
const char *name, /* I - Name of attribute */
ipp_tag_t type) /* I - Type of attribute */
{
- DEBUG_printf(("ippFindAttribute(%p, \'%s\')\n", ipp, name));
+ DEBUG_printf(("2ippFindAttribute(ipp=%p, name=\"%s\", type=%02x(%s))", ipp,
+ name, type, ippTagString(type)));
- if (ipp == NULL || name == NULL)
+ if (!ipp || !name)
return (NULL);
/*
ipp_tag_t value_tag; /* Value tag */
- DEBUG_printf(("ippFindNextAttribute(%p, \'%s\')\n", ipp, name));
+ DEBUG_printf(("2ippFindNextAttribute(ipp=%p, name=\"%s\", type=%02x(%s))",
+ ipp, name, type, ippTagString(type)));
- if (ipp == NULL || name == NULL)
+ if (!ipp || !name)
return (NULL);
if (ipp->current)
for (; attr != NULL; ipp->prev = attr, attr = attr->next)
{
- DEBUG_printf(("ippFindAttribute: attr = %p, name = \'%s\'\n", attr,
+ DEBUG_printf(("4ippFindAttribute: attr=%p, name=\"%s\"", attr,
attr->name));
value_tag = (ipp_tag_t)(attr->value_tag & IPP_TAG_MASK);
temp->request.any.version[0] = 1;
temp->request.any.version[1] = 1;
+ temp->use = 1;
}
- DEBUG_printf(("ippNew: %p\n", temp));
+ DEBUG_printf(("1ippNew: Returning %p", temp));
return (temp);
}
* attributes-natural-language attributes added. The
* attributes-natural-language value is derived from the current locale.
*
- * @since CUPS 1.2@
+ * @since CUPS 1.2/Mac OS X 10.5@
*/
ipp_t * /* O - IPP request message */
cups_lang_t *language; /* Current language localization */
+ DEBUG_printf(("ippNewRequest(op=%02x(%s))", op, ippOpString(op)));
+
/*
* Create a new IPP message...
*/
ippRead(http_t *http, /* I - HTTP connection */
ipp_t *ipp) /* I - IPP data */
{
- DEBUG_printf(("ippRead(http=%p, ipp=%p), data_remaining=" CUPS_LLFMT "\n",
+ DEBUG_printf(("ippRead(http=%p, ipp=%p), data_remaining=" CUPS_LLFMT,
http, ipp, CUPS_LLCAST (http ? http->data_remaining : -1)));
- if (http == NULL)
+ if (!http)
return (IPP_ERROR);
- DEBUG_printf(("http->state = %d\n", http->state));
+ DEBUG_printf(("2ippRead: http->state=%d, http->used=%d", http->state,
+ http->used));
- return (ippReadIO(http, (ipp_iocb_t)ipp_read_http,
- http->blocking || http->used != 0, NULL, ipp));
+ return (ippReadIO(http, (ipp_iocb_t)ipp_read_http, http->blocking, NULL,
+ ipp));
}
/*
* 'ippReadFile()' - Read data for an IPP message from a file.
*
- * @since CUPS 1.1.19@
+ * @since CUPS 1.1.19/Mac OS X 10.3@
*/
ipp_state_t /* O - Current state */
ippReadFile(int fd, /* I - HTTP data */
ipp_t *ipp) /* I - IPP data */
{
- DEBUG_printf(("ippReadFile(%d, %p)\n", fd, ipp));
+ DEBUG_printf(("ippReadFile(fd=%d, ipp=%p)", fd, ipp));
return (ippReadIO(&fd, (ipp_iocb_t)ipp_read_file, 1, NULL, ipp));
}
/*
* 'ippReadIO()' - Read data for an IPP message.
*
- * @since CUPS 1.2@
+ * @since CUPS 1.2/Mac OS X 10.5@
*/
ipp_state_t /* O - Current state */
ipp_t *ipp) /* I - IPP data */
{
int n; /* Length of data */
- unsigned char buffer[32768], /* Data buffer */
- string[255], /* Small string buffer */
+ unsigned char *buffer, /* Data buffer */
+ string[IPP_MAX_NAME],
+ /* Small string buffer */
*bufptr; /* Pointer into buffer */
ipp_attribute_t *attr; /* Current attribute */
ipp_tag_t tag; /* Current tag */
ipp_value_t *value; /* Current value */
- DEBUG_printf(("ippReadIO(%p, %p, %d, %p, %p)\n", src, cb, blocking,
- parent, ipp));
- DEBUG_printf(("ippReadIO: ipp->state=%d\n", ipp->state));
+ DEBUG_printf(("ippReadIO(src=%p, cb=%p, blocking=%d, parent=%p, ipp=%p)",
+ src, cb, blocking, parent, ipp));
+ DEBUG_printf(("2ippReadIO: ipp->state=%d", ipp->state));
- if (src == NULL || ipp == NULL)
+ if (!src || !ipp)
+ return (IPP_ERROR);
+
+ if ((buffer = ipp_buffer_get()) == NULL)
+ {
+ DEBUG_puts("1ippReadIO: Unable to get read buffer!");
return (IPP_ERROR);
+ }
switch (ipp->state)
{
* Get the request header...
*/
- if ((n = (*cb)(src, buffer, 8)) < 8)
- {
- DEBUG_printf(("ippReadIO: Unable to read header (%d bytes read)!\n", n));
- return (IPP_ERROR);
- }
-
- /*
- * Verify the major version number...
- */
-
- if (buffer[0] != 1)
+ if ((*cb)(src, buffer, 8) < 8)
{
- DEBUG_printf(("ippReadIO: version number (%d.%d) is bad.\n", buffer[0],
- buffer[1]));
+ DEBUG_puts("1ippReadIO: Unable to read header!");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
ipp->request.any.request_id = (((((buffer[4] << 8) | buffer[5]) << 8) |
buffer[6]) << 8) | buffer[7];
- DEBUG_printf(("ippReadIO: version=%d.%d\n", buffer[0], buffer[1]));
- DEBUG_printf(("ippReadIO: op_status=%04x\n",
+ DEBUG_printf(("2ippReadIO: version=%d.%d", buffer[0], buffer[1]));
+ DEBUG_printf(("2ippReadIO: op_status=%04x",
ipp->request.any.op_status));
- DEBUG_printf(("ippReadIO: request_id=%d\n",
+ DEBUG_printf(("2ippReadIO: request_id=%d",
ipp->request.any.request_id));
}
for (;;)
{
if ((*cb)(src, buffer, 1) < 1)
+ {
+ DEBUG_puts("1ippReadIO: Callback returned EOF/error");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
+ }
- DEBUG_printf(("ippReadIO: ipp->current=%p, ipp->prev=%p\n",
+ DEBUG_printf(("2ippReadIO: ipp->current=%p, ipp->prev=%p",
ipp->current, ipp->prev));
/*
* No more attributes left...
*/
- DEBUG_puts("ippReadIO: IPP_TAG_END!");
+ DEBUG_puts("2ippReadIO: IPP_TAG_END!");
ipp->state = IPP_DATA;
break;
ipp->curtag = tag;
ipp->current = NULL;
- DEBUG_printf(("ippReadIO: group tag = %x, ipp->prev=%p\n", tag,
- ipp->prev));
+ DEBUG_printf(("2ippReadIO: group tag=%x(%s), ipp->prev=%p", tag,
+ ippTagString(tag), ipp->prev));
continue;
}
- DEBUG_printf(("ippReadIO: value tag = %x\n", tag));
+ DEBUG_printf(("2ippReadIO: value tag=%x(%s)", tag,
+ ippTagString(tag)));
/*
* Get the name...
if ((*cb)(src, buffer, 2) < 2)
{
- DEBUG_puts("ippReadIO: unable to read name length!");
+ DEBUG_puts("1ippReadIO: 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));
+ DEBUG_printf(("1ippReadIO: bad name length %d!", n));
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
- DEBUG_printf(("ippReadIO: name length = %d\n", n));
+ DEBUG_printf(("2ippReadIO: name length=%d", n));
if (n == 0 && tag != IPP_TAG_MEMBERNAME &&
tag != IPP_TAG_END_COLLECTION)
*/
if (ipp->current == NULL)
+ {
+ DEBUG_puts("1ippReadIO: 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);
attr->value_tag = tag;
}
- else if (value_tag == IPP_TAG_STRING ||
- (value_tag >= IPP_TAG_TEXTLANG &&
+ else if ((value_tag >= IPP_TAG_TEXTLANG &&
value_tag <= IPP_TAG_MIMETYPE))
{
/*
* forms; accept sets of differing values...
*/
- if (tag != IPP_TAG_STRING &&
- (tag < IPP_TAG_TEXTLANG || tag > IPP_TAG_MIMETYPE))
+ if ((tag < IPP_TAG_TEXTLANG || tag > IPP_TAG_MIMETYPE) &&
+ tag != IPP_TAG_NOVALUE)
+ {
+ DEBUG_printf(("1ippReadIO: 1setOf value tag %x(%s) != %x(%s)",
+ value_tag, ippTagString(value_tag), tag,
+ ippTagString(tag)));
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
+ }
}
else if (value_tag != tag)
+ {
+ DEBUG_printf(("1ippReadIO: value tag %x(%s) != %x(%s)",
+ value_tag, ippTagString(value_tag), tag,
+ ippTagString(tag)));
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
+ }
/*
* Finally, reallocate the attribute array as needed...
ipp_attribute_t *temp; /* Pointer to new buffer */
- DEBUG_printf(("ippReadIO: reallocating for up to %d values...\n",
+ DEBUG_printf(("2ippReadIO: reallocating for up to %d values...",
attr->num_values + IPP_MAX_VALUES));
/*
if ((temp = realloc(attr, sizeof(ipp_attribute_t) +
(attr->num_values + IPP_MAX_VALUES - 1) *
sizeof(ipp_value_t))) == NULL)
+ {
+ DEBUG_puts("1ippReadIO: Unable to resize attribute");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
+ }
if (temp != attr)
{
if (n)
{
- DEBUG_puts("ippReadIO: member name not empty!");
+ DEBUG_puts("1ippReadIO: member name not empty!");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
attr = ipp->current = _ippAddAttr(ipp, 1);
- DEBUG_printf(("ippReadIO: membername, ipp->current=%p, ipp->prev=%p\n",
- ipp->current, ipp->prev));
+ DEBUG_printf(("2ippReadIO: membername, ipp->current=%p, "
+ "ipp->prev=%p", ipp->current, ipp->prev));
attr->group_tag = ipp->curtag;
attr->value_tag = IPP_TAG_ZERO;
if ((*cb)(src, buffer, n) < n)
{
- DEBUG_puts("ippReadIO: unable to read name!");
+ DEBUG_puts("1ippReadIO: unable to read name!");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
if (ipp->current)
ipp->prev = ipp->current;
- attr = ipp->current = _ippAddAttr(ipp, 1);
+ if ((attr = ipp->current = _ippAddAttr(ipp, 1)) == NULL)
+ {
+ DEBUG_puts("1ippReadIO: unable to allocate attribute!");
+ ipp_buffer_release(buffer);
+ return (IPP_ERROR);
+ }
- DEBUG_printf(("ippReadIO: name=\'%s\', ipp->current=%p, ipp->prev=%p\n",
- buffer, ipp->current, ipp->prev));
+ DEBUG_printf(("2ippReadIO: name=\"%s\", ipp->current=%p, "
+ "ipp->prev=%p", buffer, ipp->current, ipp->prev));
attr->group_tag = ipp->curtag;
attr->value_tag = tag;
if ((*cb)(src, buffer, 2) < 2)
{
- DEBUG_puts("ippReadIO: unable to read value length!");
+ DEBUG_puts("1ippReadIO: unable to read value length!");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
n = (buffer[0] << 8) | buffer[1];
- DEBUG_printf(("ippReadIO: value length = %d\n", n));
+ DEBUG_printf(("2ippReadIO: value length=%d", n));
switch (tag)
{
case IPP_TAG_INTEGER :
case IPP_TAG_ENUM :
+ if (n != 4)
+ {
+ DEBUG_printf(("1ippReadIO: bad value length %d!", n));
+ ipp_buffer_release(buffer);
+ return (IPP_ERROR);
+ }
+
if ((*cb)(src, buffer, 4) < 4)
{
- DEBUG_puts("ippReadIO: Unable to read integer value!");
+ DEBUG_puts("1ippReadIO: Unable to read integer value!");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
value->integer = n;
break;
+
case IPP_TAG_BOOLEAN :
+ if (n != 1)
+ {
+ DEBUG_printf(("1ippReadIO: bad value length %d!", n));
+ ipp_buffer_release(buffer);
+ return (IPP_ERROR);
+ }
+
if ((*cb)(src, buffer, 1) < 1)
{
- DEBUG_puts("ippReadIO: Unable to read boolean value!");
+ DEBUG_puts("1ippReadIO: Unable to read boolean value!");
+ 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 :
+ /*
+ * These value types are not supposed to have values, however
+ * some vendors (Brother) do not implement IPP correctly and so
+ * we need to map non-empty values to text...
+ */
+
+ 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_STRING :
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)
+ {
+ DEBUG_printf(("1ippReadIO: bad value length %d!", n));
+ ipp_buffer_release(buffer);
+ return (IPP_ERROR);
+ }
+
if ((*cb)(src, buffer, n) < n)
{
- DEBUG_puts("ippReadIO: unable to read name!");
+ DEBUG_puts("1ippReadIO: unable to read name!");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
buffer[n] = '\0';
value->string.text = _cupsStrAlloc((char *)buffer);
- DEBUG_printf(("ippReadIO: value = \'%s\'\n",
- value->string.text));
+ DEBUG_printf(("2ippReadIO: value=\"%s\"", value->string.text));
break;
+
case IPP_TAG_DATE :
+ if (n != 11)
+ {
+ DEBUG_printf(("1ippReadIO: bad value length %d!", n));
+ ipp_buffer_release(buffer);
+ return (IPP_ERROR);
+ }
+
if ((*cb)(src, value->date, 11) < 11)
{
- DEBUG_puts("ippReadIO: Unable to date integer value!");
+ DEBUG_puts("1ippReadIO: Unable to read date value!");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
break;
+
case IPP_TAG_RESOLUTION :
+ if (n != 9)
+ {
+ DEBUG_printf(("1ippReadIO: bad value length %d!", n));
+ ipp_buffer_release(buffer);
+ return (IPP_ERROR);
+ }
+
if ((*cb)(src, buffer, 9) < 9)
{
- DEBUG_puts("ippReadIO: Unable to read resolution value!");
+ DEBUG_puts("1ippReadIO: Unable to read resolution value!");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
value->resolution.units =
(ipp_res_t)buffer[8];
break;
+
case IPP_TAG_RANGE :
+ if (n != 8)
+ {
+ DEBUG_printf(("1ippReadIO: bad value length %d!", n));
+ ipp_buffer_release(buffer);
+ return (IPP_ERROR);
+ }
+
if ((*cb)(src, buffer, 8) < 8)
{
- DEBUG_puts("ippReadIO: Unable to read range value!");
+ DEBUG_puts("1ippReadIO: Unable to read range value!");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
(((((buffer[4] << 8) | buffer[5]) << 8) | buffer[6]) << 8) |
buffer[7];
break;
+
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));
+ DEBUG_printf(("1ippReadIO: bad value length %d!", n));
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
if ((*cb)(src, buffer, n) < n)
{
- DEBUG_puts("ippReadIO: Unable to read string w/language value!");
+ DEBUG_puts("1ippReadIO: Unable to read string w/language "
+ "value!");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
n = (bufptr[0] << 8) | bufptr[1];
- if (n >= sizeof(string))
+ if ((bufptr + 2 + n) >= (buffer + IPP_BUF_SIZE) ||
+ n >= sizeof(string))
{
- memcpy(string, bufptr + 2, sizeof(string) - 1);
- string[sizeof(string) - 1] = '\0';
+ DEBUG_printf(("1ippReadIO: bad value length %d!", n));
+ ipp_buffer_release(buffer);
+ return (IPP_ERROR);
}
- else
- {
- memcpy(string, bufptr + 2, n);
- string[n] = '\0';
- }
+
+ memcpy(string, bufptr + 2, n);
+ string[n] = '\0';
value->string.charset = _cupsStrAlloc((char *)string);
bufptr += 2 + n;
n = (bufptr[0] << 8) | bufptr[1];
+ if ((bufptr + 2 + n) >= (buffer + IPP_BUF_SIZE))
+ {
+ DEBUG_printf(("1ippReadIO: bad value length %d!", n));
+ ipp_buffer_release(buffer);
+ return (IPP_ERROR);
+ }
+
bufptr[2 + n] = '\0';
value->string.text = _cupsStrAlloc((char *)bufptr + 2);
break;
if (n > 0)
{
- DEBUG_puts("ippReadIO: begCollection tag with value length > 0!");
+ DEBUG_puts("1ippReadIO: 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!");
+ DEBUG_puts("1ippReadIO: 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 > 0!");
+ DEBUG_puts("1ippReadIO: endCollection tag with value length "
+ "> 0!");
return (IPP_ERROR);
}
- DEBUG_puts("ippReadIO: endCollection tag...");
-
+ DEBUG_puts("1ippReadIO: endCollection tag...");
return (ipp->state = IPP_DATA);
case IPP_TAG_MEMBERNAME :
* we need to carry over...
*/
+ if (n >= IPP_BUF_SIZE)
+ {
+ DEBUG_printf(("1ippReadIO: bad value length %d!", n));
+ ipp_buffer_release(buffer);
+ return (IPP_ERROR);
+ }
+
if ((*cb)(src, buffer, n) < n)
{
- DEBUG_puts("ippReadIO: Unable to read member name value!");
+ DEBUG_puts("1ippReadIO: Unable to read member name value!");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
attr->num_values --;
- DEBUG_printf(("ippReadIO: member name = \"%s\"\n", attr->name));
+ DEBUG_printf(("2ippReadIO: member name=\"%s\"", attr->name));
break;
default : /* Other unsupported values */
+ if (n > IPP_MAX_LENGTH)
+ {
+ DEBUG_printf(("1ippReadIO: bad value length %d!", n));
+ ipp_buffer_release(buffer);
+ return (IPP_ERROR);
+ }
+
+ if (!value)
+ {
+ DEBUG_puts("1ippReadIO: NULL value!");
+ ipp_buffer_release(buffer);
+ return (IPP_ERROR);
+ }
+
value->unknown.length = n;
if (n > 0)
{
- value->unknown.data = malloc(n);
+ if ((value->unknown.data = malloc(n)) == NULL)
+ {
+ DEBUG_puts("1ippReadIO: 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!");
+ DEBUG_puts("1ippReadIO: Unable to read unsupported value!");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
}
break; /* anti-compiler-warning-code */
}
- DEBUG_printf(("ippReadIO: returning ipp->state=%d!\n", ipp->state));
+ DEBUG_printf(("1ippReadIO: returning ipp->state=%d!", ipp->state));
+ ipp_buffer_release(buffer);
return (ipp->state);
}
ippWrite(http_t *http, /* I - HTTP connection */
ipp_t *ipp) /* I - IPP data */
{
- DEBUG_printf(("ippWrite(%p, %p)\n", http, ipp));
+ DEBUG_printf(("ippWrite(http=%p, ipp=%p)", http, ipp));
- if (http == NULL)
+ if (!http)
return (IPP_ERROR);
- return (ippWriteIO(http, (ipp_iocb_t)httpWrite2,
- http->blocking, NULL, ipp));
+ return (ippWriteIO(http, (ipp_iocb_t)httpWrite2, http->blocking, NULL, ipp));
}
/*
* 'ippWriteFile()' - Write data for an IPP message to a file.
*
- * @since CUPS 1.1.19@
+ * @since CUPS 1.1.19/Mac OS X 10.3@
*/
ipp_state_t /* O - Current state */
ippWriteFile(int fd, /* I - HTTP data */
ipp_t *ipp) /* I - IPP data */
{
- DEBUG_printf(("ippWriteFile(%d, %p)\n", fd, ipp));
+ DEBUG_printf(("ippWriteFile(fd=%d, ipp=%p)", fd, ipp));
ipp->state = IPP_IDLE;
/*
* 'ippWriteIO()' - Write data for an IPP message.
*
- * @since CUPS 1.2@
+ * @since CUPS 1.2/Mac OS X 10.5@
*/
ipp_state_t /* O - Current state */
{
int i; /* Looping var */
int n; /* Length of data */
- unsigned char buffer[32768], /* Data buffer */
+ unsigned char *buffer, /* Data buffer */
*bufptr; /* Pointer into buffer */
ipp_attribute_t *attr; /* Current attribute */
ipp_value_t *value; /* Current value */
- DEBUG_printf(("ippWriteIO(%p, %p, %d, %p, %p)\n", dst, cb, blocking,
- parent, ipp));
+ DEBUG_printf(("ippWriteIO(dst=%p, cb=%p, blocking=%d, parent=%p, ipp=%p)",
+ dst, cb, blocking, parent, ipp));
- if (dst == NULL || ipp == NULL)
+ if (!dst || !ipp)
return (IPP_ERROR);
+ if ((buffer = ipp_buffer_get()) == NULL)
+ {
+ DEBUG_puts("1ippWriteIO: Unable to get write buffer");
+ return (IPP_ERROR);
+ }
+
switch (ipp->state)
{
case IPP_IDLE :
*bufptr++ = ipp->request.any.request_id >> 8;
*bufptr++ = ipp->request.any.request_id;
+ DEBUG_printf(("2ippWriteIO: version=%d.%d", buffer[0], buffer[1]));
+ DEBUG_printf(("2ippWriteIO: op_status=%04x",
+ ipp->request.any.op_status));
+ DEBUG_printf(("2ippWriteIO: request_id=%d",
+ ipp->request.any.request_id));
+
if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
{
- DEBUG_puts("ippWriteIO: Could not write IPP header...");
+ DEBUG_puts("1ippWriteIO: Could not write IPP header...");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
}
ipp->current = ipp->attrs;
ipp->curtag = IPP_TAG_ZERO;
- DEBUG_printf(("ippWriteIO: version=%d.%d\n", buffer[0], buffer[1]));
- DEBUG_printf(("ippWriteIO: op_status=%04x\n", ipp->request.any.op_status));
- DEBUG_printf(("ippWriteIO: request_id=%d\n", ipp->request.any.request_id));
+ DEBUG_printf(("1ippWriteIO: ipp->current=%p", ipp->current));
/*
* If blocking is disabled, stop here...
ipp->current = ipp->current->next;
- if (ipp->curtag != attr->group_tag && parent == NULL)
+ if (!parent)
{
- /*
- * Send a group tag byte...
- */
+ if (ipp->curtag != attr->group_tag)
+ {
+ /*
+ * Send a group tag byte...
+ */
- ipp->curtag = attr->group_tag;
+ ipp->curtag = attr->group_tag;
- if (attr->group_tag == IPP_TAG_ZERO)
- continue;
+ if (attr->group_tag == IPP_TAG_ZERO)
+ continue;
- DEBUG_printf(("ippWriteIO: wrote group tag = %x\n", attr->group_tag));
- *bufptr++ = attr->group_tag;
+ DEBUG_printf(("2ippWriteIO: wrote group tag=%x(%s)",
+ attr->group_tag, ippTagString(attr->group_tag)));
+ *bufptr++ = attr->group_tag;
+ }
+ else if (attr->group_tag == IPP_TAG_ZERO)
+ continue;
}
- else if (attr->group_tag == IPP_TAG_ZERO)
- continue;
+
+ DEBUG_printf(("1ippWriteIO: %s (%s%s)", attr->name,
+ attr->num_values > 1 ? "1setOf " : "",
+ ippTagString(attr->value_tag)));
/*
* Write the attribute tag and name. The current implementation
* overflow the buffer...
*/
- if ((n = (int)strlen(attr->name)) > (sizeof(buffer) - 4))
+ if ((n = (int)strlen(attr->name)) > (IPP_BUF_SIZE - 4))
+ {
+ DEBUG_printf(("1ippWriteIO: Attribute name too long (%d)", n));
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
+ }
/*
* Write the value tag, name length, and name string...
*/
- DEBUG_printf(("ippWriteIO: writing value tag = %x\n", attr->value_tag));
- DEBUG_printf(("ippWriteIO: writing name = %d, \'%s\'\n", n, attr->name));
+ DEBUG_printf(("2ippWriteIO: writing value tag=%x(%s)",
+ attr->value_tag, ippTagString(attr->value_tag)));
+ DEBUG_printf(("2ippWriteIO: writing name=%d,\"%s\"", n,
+ attr->name));
*bufptr++ = attr->value_tag;
*bufptr++ = n >> 8;
* overflow the buffer...
*/
- if ((n = (int)strlen(attr->name)) > (sizeof(buffer) - 7))
+ if ((n = (int)strlen(attr->name)) > (IPP_BUF_SIZE - 7))
+ {
+ DEBUG_printf(("1ippWriteIO: Attribute name too long (%d)", n));
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
+ }
/*
* Write the member name tag, name length, name string, value tag,
* and empty name for the collection member attribute...
*/
- DEBUG_printf(("ippWriteIO: writing value tag = %x\n",
+ DEBUG_printf(("2ippWriteIO: writing value tag=%x(memberName)",
IPP_TAG_MEMBERNAME));
- DEBUG_printf(("ippWriteIO: writing name = %d, \'%s\'\n", n, attr->name));
- DEBUG_printf(("ippWriteIO: writing value tag = %x\n", attr->value_tag));
- DEBUG_puts("ippWriteIO: writing name = 0, \'\'\n");
+ DEBUG_printf(("2ippWriteIO: writing name=%d,\"%s\"", n,
+ attr->name));
+ DEBUG_printf(("2ippWriteIO: writing value tag=%x(%s)",
+ attr->value_tag, ippTagString(attr->value_tag)));
+ DEBUG_puts("2ippWriteIO: writing name=0,\"\"");
*bufptr++ = IPP_TAG_MEMBERNAME;
*bufptr++ = 0;
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...");
+ DEBUG_puts("1ippWriteIO: 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...");
+ DEBUG_puts("1ippWriteIO: Could not write IPP "
+ "attribute...");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
case IPP_TAG_TEXT :
case IPP_TAG_NAME :
case IPP_TAG_KEYWORD :
- case IPP_TAG_STRING :
case IPP_TAG_URI :
case IPP_TAG_URISCHEME :
case IPP_TAG_CHARSET :
* values with a zero-length name...
*/
- DEBUG_printf(("ippWriteIO: writing value tag = %x\n",
- attr->value_tag));
- DEBUG_printf(("ippWriteIO: writing name = 0, \'\'\n"));
+ DEBUG_printf(("2ippWriteIO: writing value tag=%x(%s)",
+ attr->value_tag,
+ ippTagString(attr->value_tag)));
+ DEBUG_printf(("2ippWriteIO: writing name=0,\"\""));
- 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...");
+ DEBUG_puts("1ippWriteIO: 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(("1ippWriteIO: String too long (%d)", n));
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
+ }
- DEBUG_printf(("ippWriteIO: writing string = %d, \'%s\'\n", n,
+ DEBUG_printf(("2ippWriteIO: writing string=%d,\"%s\"", 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...");
+ DEBUG_puts("1ippWriteIO: Could not write IPP "
+ "attribute...");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
/*
* All simple strings consist of the 2-byte length and
* character data without the trailing nul normally found
- * in C strings. Also, strings cannot be longer than 32767
+ * in C strings. Also, strings cannot be longer than IPP_MAX_LENGTH
* bytes since the 2-byte length is a signed (twos-complement)
* value.
*
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...");
+ DEBUG_puts("1ippWriteIO: 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);
+ DEBUG_puts("1ippWriteIO: Could not write IPP "
+ "attribute...");
+ 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...");
+ DEBUG_puts("1ippWriteIO: 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...");
+ DEBUG_puts("1ippWriteIO: 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(("1ippWriteIO: text/nameWithLanguage value "
+ "too long (%d)", 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...");
+ DEBUG_puts("1ippWriteIO: 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...");
+ DEBUG_puts("1ippWriteIO: 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...");
+ DEBUG_puts("1ippWriteIO: 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("1ippWriteIO: 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...");
+ DEBUG_puts("1ippWriteIO: 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(("1ippWriteIO: Data length too long (%d)",
+ 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...");
+ DEBUG_puts("1ippWriteIO: Could not write IPP "
+ "attribute...");
+ ipp_buffer_release(buffer);
return (IPP_ERROR);
}
* Write the data out...
*/
- if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
+ if (bufptr > buffer)
{
- DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
- return (IPP_ERROR);
- }
+ if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
+ {
+ DEBUG_puts("1ippWriteIO: Could not write IPP attribute...");
+ ipp_buffer_release(buffer);
+ return (IPP_ERROR);
+ }
- DEBUG_printf(("ippWriteIO: wrote %d bytes\n", bufptr - buffer));
+ DEBUG_printf(("2ippWriteIO: wrote %d bytes",
+ (int)(bufptr - buffer)));
+ }
/*
* If blocking is disabled, stop here...
if ((*cb)(dst, buffer, n) < 0)
{
- DEBUG_puts("ippWriteIO: Could not write IPP end-tag...");
+ DEBUG_puts("1ippWriteIO: 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_attribute_t *attr; /* New attribute */
- DEBUG_printf(("_ippAddAttr(%p, %d)\n", ipp, num_values));
+ DEBUG_printf(("4_ippAddAttr(ipp=%p, num_values=%d)", ipp, num_values));
- if (ipp == NULL || num_values < 0)
+ if (!ipp || num_values < 0)
return (NULL);
attr = calloc(sizeof(ipp_attribute_t) +
ipp->last = attr;
}
- DEBUG_printf(("_ippAddAttr(): %p\n", attr));
+ DEBUG_printf(("5_ippAddAttr: Returning %p", attr));
return (attr);
}
ipp_value_t *value; /* Current value */
- DEBUG_printf(("_ippFreeAttr(): %p\n", attr));
+ DEBUG_printf(("4_ippFreeAttr(attr=%p)", attr));
switch (attr->value_tag)
{
case IPP_TAG_TEXT :
case IPP_TAG_NAME :
case IPP_TAG_KEYWORD :
- case IPP_TAG_STRING :
case IPP_TAG_URI :
case IPP_TAG_URISCHEME :
case IPP_TAG_CHARSET :
ippDelete(value->collection);
break;
+ case IPP_TAG_STRING :
+ for (i = 0, value = attr->values;
+ i < attr->num_values;
+ i ++, value ++)
+ free(value->unknown.data);
+ break;
+
default :
if (!((int)attr->value_tag & IPP_TAG_COPY))
{
}
+/*
+ * '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.
*/
if (!attr->name)
continue;
- DEBUG_printf(("attr->name = %s, attr->num_values = %d, bytes = %d\n",
- attr->name, attr->num_values, bytes));
+ DEBUG_printf(("9ipp_length: attr->name=\"%s\", attr->num_values=%d, "
+ "bytes=%d", attr->name, attr->num_values, bytes));
bytes += (int)strlen(attr->name); /* Name */
bytes += attr->num_values; /* Value tag for each value */
case IPP_TAG_TEXT :
case IPP_TAG_NAME :
case IPP_TAG_KEYWORD :
- case IPP_TAG_STRING :
case IPP_TAG_URI :
case IPP_TAG_URISCHEME :
case IPP_TAG_CHARSET :
else
bytes ++;
- DEBUG_printf(("bytes = %d\n", bytes));
+ DEBUG_printf(("8ipp_length: Returning %d bytes", bytes));
return (bytes);
}
int tbytes, /* Total bytes read */
bytes; /* Bytes read this pass */
char len[32]; /* Length string */
-
- DEBUG_printf(("ipp_read_http(http=%p, buffer=%p, length=%d)\n",
- http, buffer, length));
+
+ DEBUG_printf(("7ipp_read_http(http=%p, buffer=%p, length=%d)",
+ http, buffer, (int)length));
/*
* Loop until all bytes are read...
*/
- for (tbytes = 0, bytes = 0; tbytes < (int)length; tbytes += bytes, buffer += bytes)
+ for (tbytes = 0, bytes = 0;
+ tbytes < (int)length;
+ tbytes += bytes, buffer += bytes)
{
- DEBUG_printf(("tbytes = %d, http->state = %d\n", tbytes, http->state));
+ DEBUG_printf(("9ipp_read_http: tbytes=%d, http->state=%d", tbytes,
+ http->state));
if (http->state == HTTP_WAITING)
break;
}
}
- if ((bytes = httpRead2(http, (char *)buffer, length - tbytes)) <= 0)
+ if ((bytes = httpRead2(http, (char *)buffer, length - tbytes)) < 0)
+ {
+#ifdef WIN32
+ break;
+#else
+ if (errno != EAGAIN && errno != EINTR)
+ break;
+
+ bytes = 0;
+#endif /* WIN32 */
+ }
+ else if (bytes == 0)
break;
}
}
if (tbytes == 0 && bytes < 0)
tbytes = -1;
- DEBUG_printf(("returning %d bytes...\n", tbytes));
+ DEBUG_printf(("8ipp_read_http: Returning %d bytes", tbytes));
return (tbytes);
}
/*
- * End of "$Id: ipp.c 6234 2007-02-05 20:25:50Z mike $".
+ * End of "$Id: ipp.c 7847 2008-08-19 04:22:14Z mike $".
*/