]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - cups/ipp.c
Merge changes from CUPS 1.4svn-r7994.
[thirdparty/cups.git] / cups / ipp.c
index 0749ec2a1b13a6a32ad0bfc8b558d41029547b89..f9bbb5c96f8aa48f9fa4f6c2504950dd604cdc21 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: ipp.c 6649 2007-07-11 21:46:42Z mike $"
+ * "$Id: ipp.c 7847 2008-08-19 04:22:14Z mike $"
  *
  *   Internet Printing Protocol support functions for the Common UNIX
  *   Printing System (CUPS).
@@ -75,6 +75,8 @@
  * 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);
@@ -97,9 +99,10 @@ ippAddBoolean(ipp_t      *ipp,               /* I - IPP message */
   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)\n",
+                ipp, group, ippTagString(group), name, value));
 
-  if (ipp == NULL || name == NULL)
+  if (!ipp || !name)
     return (NULL);
 
   if ((attr = _ippAddAttr(ipp, 1)) == NULL)
@@ -130,10 +133,11 @@ ippAddBooleans(ipp_t      *ipp,           /* I - IPP message */
   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)\n", 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)
@@ -168,10 +172,10 @@ ippAddCollection(ipp_t      *ipp, /* I - IPP message */
   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)\n", ipp, group, ippTagString(group), name, value));
 
-  if (ipp == NULL || name == NULL)
+  if (!ipp || !name)
     return (NULL);
 
   if ((attr = _ippAddAttr(ipp, 1)) == NULL)
@@ -205,10 +209,11 @@ ippAddCollections(
   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)\n", 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)
@@ -241,10 +246,10 @@ ippAddDate(ipp_t             *ipp,        /* I - IPP message */
   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)\n",
+                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)
@@ -273,10 +278,11 @@ ippAddInteger(ipp_t      *ipp,            /* I - IPP message */
   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)\n", 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)
@@ -308,7 +314,12 @@ ippAddIntegers(ipp_t      *ipp,            /* I - IPP message */
   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)\n", 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)
@@ -395,7 +406,12 @@ ippAddString(ipp_t      *ipp,              /* I - IPP message */
                        *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\")\n", ipp,
+               group, ippTagString(group), type, ippTagString(type), name,
+               charset, value));
+
+  if (!ipp || !name)
     return (NULL);
 
   if ((attr = _ippAddAttr(ipp, 1)) == NULL)
@@ -459,7 +475,12 @@ ippAddStrings(
   ipp_value_t          *value;         /* Current value */
 
 
-  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)\n", 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)
@@ -516,7 +537,11 @@ ippAddRange(ipp_t      *ipp,               /* I - IPP message */
   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)\n", ipp, group, ippTagString(group), name, lower,
+               upper));
+
+  if (!ipp || !name)
     return (NULL);
 
   if ((attr = _ippAddAttr(ipp, 1)) == NULL)
@@ -549,7 +574,11 @@ ippAddRanges(ipp_t      *ipp,              /* I - IPP message */
   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)\n", ipp, group,
+               ippTagString(group), name, num_values, lower, upper));
+
+  if (!ipp || !name || num_values < 1)
     return (NULL);
 
   if ((attr = _ippAddAttr(ipp, num_values)) == NULL)
@@ -587,7 +616,11 @@ ippAddResolution(ipp_t      *ipp,  /* I - IPP message */
   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)\n", ipp, group,
+               ippTagString(group), name, units, xres, yres));
+
+  if (!ipp || !name)
     return (NULL);
 
   if ((attr = _ippAddAttr(ipp, 1)) == NULL)
@@ -622,7 +655,11 @@ ippAddResolutions(ipp_t      *ipp, /* I - IPP message */
   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)\n", 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)
@@ -656,9 +693,9 @@ ippAddSeparator(ipp_t *ipp)         /* I - IPP message */
   ipp_attribute_t      *attr;          /* New attribute */
 
 
-  DEBUG_printf(("ippAddSeparator(%p)\n", ipp));
+  DEBUG_printf(("ippAddSeparator(ipp=%p)\n", ipp));
 
-  if (ipp == NULL)
+  if (!ipp)
     return (NULL);
 
   if ((attr = _ippAddAttr(ipp, 0)) == NULL)
@@ -683,6 +720,9 @@ ippDateToTime(const ipp_uchar_t *date)      /* I - RFC 1903 date info */
   time_t       t;                      /* Computed time */
 
 
+  if (!date)
+    return (0);
+
   memset(&unixdate, 0, sizeof(unixdate));
 
  /*
@@ -731,9 +771,9 @@ ippDelete(ipp_t *ipp)                       /* I - IPP message */
                        *next;          /* Next attribute */
 
 
-  DEBUG_printf(("ippDelete(): %p\n", ipp));
+  DEBUG_printf(("ippDelete(ipp=%p)\n", ipp));
 
-  if (ipp == NULL)
+  if (!ipp)
     return;
 
   for (attr = ipp->attrs; attr != NULL; attr = next)
@@ -761,6 +801,8 @@ ippDeleteAttribute(
                        *prev;          /* Previous attribute */
 
 
+  DEBUG_printf(("ippDeleteAttribute(ipp=%p, attr=%p)\n", ipp, attr));
+
  /*
   * Find the attribute in the list...
   */
@@ -801,9 +843,10 @@ ippFindAttribute(ipp_t      *ipp,  /* I - IPP message */
                  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(("ippFindAttribute(ipp=%p, name=\"%s\", type=%02x(%s))\n", ipp,
+                name, type, ippTagString(type)));
 
-  if (ipp == NULL || name == NULL)
+  if (!ipp || !name)
     return (NULL);
 
  /*
@@ -833,9 +876,10 @@ ippFindNextAttribute(ipp_t      *ipp,      /* I - IPP message */
   ipp_tag_t            value_tag;      /* Value tag */
 
 
-  DEBUG_printf(("ippFindNextAttribute(%p, \'%s\')\n", ipp, name));
+  DEBUG_printf(("ippFindNextAttribute(ipp=%p, name=\"%s\", type=%02x(%s))\n",
+                ipp, name, type, ippTagString(type)));
 
-  if (ipp == NULL || name == NULL)
+  if (!ipp || !name)
     return (NULL);
 
   if (ipp->current)
@@ -851,7 +895,7 @@ ippFindNextAttribute(ipp_t      *ipp,       /* I - IPP message */
 
   for (; attr != NULL; ipp->prev = attr, attr = attr->next)
   {
-    DEBUG_printf(("ippFindAttribute: attr = %p, name = \'%s\'\n", attr,
+    DEBUG_printf(("ippFindAttribute: attr=%p, name=\"%s\"\n", attr,
                   attr->name));
 
     value_tag = (ipp_tag_t)(attr->value_tag & IPP_TAG_MASK);
@@ -930,6 +974,8 @@ ippNewRequest(ipp_op_t op)          /* I - Operation code */
   cups_lang_t  *language;              /* Current language localization */
 
 
+  DEBUG_printf(("ippNewRequest(op=%02x(%s))\n", op, ippOpString(op)));
+
  /*
   * Create a new IPP message...
   */
@@ -979,7 +1025,7 @@ ippRead(http_t *http,                      /* I - HTTP connection */
   DEBUG_printf(("ippRead(http=%p, ipp=%p), data_remaining=" CUPS_LLFMT "\n",
                 http, ipp, CUPS_LLCAST (http ? http->data_remaining : -1)));
 
-  if (http == NULL)
+  if (!http)
     return (IPP_ERROR);
 
   DEBUG_printf(("ippRead: http->state=%d, http->used=%d\n", http->state,
@@ -1000,7 +1046,7 @@ 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)\n", fd, ipp));
 
   return (ippReadIO(&fd, (ipp_iocb_t)ipp_read_file, 1, NULL, ipp));
 }
@@ -1020,8 +1066,7 @@ ippReadIO(void       *src,                /* I - Data source */
           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 */
@@ -1035,9 +1080,15 @@ ippReadIO(void       *src,               /* I - Data source */
                 src, cb, blocking, parent, ipp));
   DEBUG_printf(("ippReadIO: ipp->state=%d\n", ipp->state));
 
-  if (src == NULL || ipp == NULL)
+  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 :
@@ -1050,9 +1101,10 @@ ippReadIO(void       *src,               /* I - Data source */
           * Get the request header...
          */
 
-          if ((n = (*cb)(src, buffer, 8)) < 8)
+          if ((*cb)(src, buffer, 8) < 8)
          {
-           DEBUG_printf(("ippReadIO: Unable to read header (%d bytes read)!\n", n));
+           DEBUG_puts("ippReadIO: Unable to read header!");
+           ipp_buffer_release(buffer);
            return (IPP_ERROR);
          }
 
@@ -1062,8 +1114,9 @@ ippReadIO(void       *src,                /* I - Data source */
 
          if (buffer[0] != 1)
          {
-           DEBUG_printf(("ippReadIO: version number (%d.%d) is bad.\n", buffer[0],
-                         buffer[1]));
+           DEBUG_printf(("ippReadIO: version number (%d.%d) is bad.\n",
+                         buffer[0], buffer[1]));
+           ipp_buffer_release(buffer);
            return (IPP_ERROR);
          }
 
@@ -1100,7 +1153,11 @@ ippReadIO(void       *src,               /* I - Data source */
         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));
@@ -1135,12 +1192,13 @@ ippReadIO(void       *src,              /* I - Data source */
 
            ipp->curtag  = tag;
            ipp->current = NULL;
-           DEBUG_printf(("ippReadIO: group tag = %x, ipp->prev=%p\n", tag,
-                         ipp->prev));
+           DEBUG_printf(("ippReadIO: group tag=%x(%s), ipp->prev=%p\n", tag,
+                         ippTagString(tag), ipp->prev));
            continue;
          }
 
-          DEBUG_printf(("ippReadIO: value tag = %x\n", tag));
+          DEBUG_printf(("ippReadIO: value tag=%x(%s)\n", tag,
+                       ippTagString(tag)));
 
          /*
          * Get the name...
@@ -1149,18 +1207,20 @@ ippReadIO(void       *src,              /* I - Data source */
           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);
          }
 
-          DEBUG_printf(("ippReadIO: name length = %d\n", n));
+          DEBUG_printf(("ippReadIO: name length=%d\n", n));
 
           if (n == 0 && tag != IPP_TAG_MEMBERNAME &&
              tag != IPP_TAG_END_COLLECTION)
@@ -1170,7 +1230,11 @@ ippReadIO(void       *src,               /* I - Data source */
            */
 
             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);
@@ -1188,19 +1252,32 @@ ippReadIO(void       *src,              /* I - Data source */
 
              attr->value_tag = tag;
            }
-           else if (value_tag >= IPP_TAG_TEXTLANG &&
-                    value_tag <= IPP_TAG_MIMETYPE)
+           else if ((value_tag >= IPP_TAG_TEXTLANG &&
+                     value_tag <= IPP_TAG_MIMETYPE))
             {
             /*
              * String values can sometimes come across in different
              * forms; accept sets of differing values...
              */
 
-             if (tag < IPP_TAG_TEXTLANG || tag > IPP_TAG_MIMETYPE)
+             if ((tag < IPP_TAG_TEXTLANG || tag > IPP_TAG_MIMETYPE) &&
+                 tag != IPP_TAG_NOVALUE)
+             {
+               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);
+             }
             }
            else if (value_tag != tag)
+           {
+             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);
+            }
 
            /*
            * Finally, reallocate the attribute array as needed...
@@ -1223,7 +1300,11 @@ ippReadIO(void       *src,               /* I - Data source */
               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)
              {
@@ -1249,6 +1330,7 @@ ippReadIO(void       *src,                /* I - Data source */
            if (n)
            {
              DEBUG_puts("ippReadIO: member name not empty!");
+             ipp_buffer_release(buffer);
              return (IPP_ERROR);
            }
 
@@ -1257,8 +1339,8 @@ ippReadIO(void       *src,                /* I - Data source */
 
            attr = ipp->current = _ippAddAttr(ipp, 1);
 
-           DEBUG_printf(("ippReadIO: membername, ipp->current=%p, ipp->prev=%p\n",
-                         ipp->current, ipp->prev));
+           DEBUG_printf(("ippReadIO: membername, ipp->current=%p, "
+                         "ipp->prev=%p\n", ipp->current, ipp->prev));
 
            attr->group_tag  = ipp->curtag;
            attr->value_tag  = IPP_TAG_ZERO;
@@ -1273,6 +1355,7 @@ ippReadIO(void       *src,                /* I - Data source */
            if ((*cb)(src, buffer, n) < n)
            {
              DEBUG_puts("ippReadIO: unable to read name!");
+             ipp_buffer_release(buffer);
              return (IPP_ERROR);
            }
 
@@ -1284,11 +1367,12 @@ ippReadIO(void       *src,              /* I - Data source */
            if ((attr = ipp->current = _ippAddAttr(ipp, 1)) == NULL)
            {
              DEBUG_puts("ippReadIO: 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(("ippReadIO: name=\"%s\", ipp->current=%p, "
+                         "ipp->prev=%p\n", buffer, ipp->current, ipp->prev));
 
            attr->group_tag  = ipp->curtag;
            attr->value_tag  = tag;
@@ -1306,11 +1390,12 @@ ippReadIO(void       *src,              /* I - Data source */
          if ((*cb)(src, buffer, 2) < 2)
          {
            DEBUG_puts("ippReadIO: 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(("ippReadIO: value length=%d\n", n));
 
          switch (tag)
          {
@@ -1319,12 +1404,14 @@ ippReadIO(void       *src,              /* I - Data source */
                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);
                }
 
@@ -1338,18 +1425,29 @@ ippReadIO(void       *src,              /* I - Data source */
                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);
                }
 
                 value->boolean = buffer[0];
                break;
 
+            case IPP_TAG_NOVALUE :
+               if (attr->value_tag == IPP_TAG_NOVALUE)
+               {
+                 if (n == 0)
+                   break;
+
+                 attr->value_tag = IPP_TAG_TEXT;
+               }
+
            case IPP_TAG_TEXT :
            case IPP_TAG_NAME :
            case IPP_TAG_KEYWORD :
@@ -1358,21 +1456,23 @@ ippReadIO(void       *src,              /* I - Data source */
            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);
                }
 
                buffer[n] = '\0';
                value->string.text = _cupsStrAlloc((char *)buffer);
-               DEBUG_printf(("ippReadIO: value = \'%s\'\n",
+               DEBUG_printf(("ippReadIO: value=\"%s\"\n",
                              value->string.text));
                break;
 
@@ -1380,12 +1480,14 @@ ippReadIO(void       *src,              /* I - Data source */
                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;
@@ -1394,12 +1496,14 @@ ippReadIO(void       *src,              /* I - Data source */
                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);
                }
 
@@ -1417,12 +1521,14 @@ ippReadIO(void       *src,              /* I - Data source */
                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);
                }
 
@@ -1436,15 +1542,17 @@ ippReadIO(void       *src,              /* I - Data source */
 
            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);
                }
 
@@ -1462,10 +1570,11 @@ ippReadIO(void       *src,              /* I - Data source */
 
                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);
                }
 
@@ -1477,9 +1586,10 @@ ippReadIO(void       *src,               /* I - Data source */
                 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);
                }
 
@@ -1496,26 +1606,31 @@ ippReadIO(void       *src,              /* I - Data source */
 
                 if (n > 0)
                {
-                 DEBUG_puts("ippReadIO: begCollection tag with value length > 0!");
+                 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 > 0!");
+                 DEBUG_puts("ippReadIO: endCollection tag with value length "
+                            "> 0!");
                  return (IPP_ERROR);
                }
 
                DEBUG_puts("ippReadIO: endCollection tag...");
-
                return (ipp->state = IPP_DATA);
 
             case IPP_TAG_MEMBERNAME :
@@ -1524,15 +1639,17 @@ ippReadIO(void       *src,              /* I - Data source */
                * 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);
                }
 
@@ -1547,13 +1664,21 @@ ippReadIO(void       *src,              /* I - Data source */
 
                 attr->num_values --;
 
-               DEBUG_printf(("ippReadIO: member name = \"%s\"\n", attr->name));
+               DEBUG_printf(("ippReadIO: member name=\"%s\"\n", attr->name));
                break;
 
             default : /* Other unsupported values */
                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);
                }
 
@@ -1563,12 +1688,14 @@ ippReadIO(void       *src,              /* I - Data source */
                  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);
                  }
                }
@@ -1596,6 +1723,7 @@ ippReadIO(void       *src,                /* I - Data source */
   }
 
   DEBUG_printf(("ippReadIO: returning ipp->state=%d!\n", ipp->state));
+  ipp_buffer_release(buffer);
 
   return (ipp->state);
 }
@@ -1657,9 +1785,9 @@ ipp_state_t                               /* O - Current 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)\n", http, ipp));
 
-  if (http == NULL)
+  if (!http)
     return (IPP_ERROR);
 
   return (ippWriteIO(http, (ipp_iocb_t)httpWrite2,
@@ -1677,7 +1805,7 @@ 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)\n", fd, ipp));
 
   ipp->state = IPP_IDLE;
 
@@ -1700,19 +1828,24 @@ ippWriteIO(void       *dst,             /* I - Destination */
 {
   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 */
 
 
-  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)\n",
+                dst, cb, blocking, parent, ipp));
 
-  if (dst == NULL || ipp == NULL)
+  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 :
@@ -1744,6 +1877,7 @@ ippWriteIO(void       *dst,               /* I - Destination */
           if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
          {
            DEBUG_puts("ippWriteIO: Could not write IPP header...");
+           ipp_buffer_release(buffer);
            return (IPP_ERROR);
          }
        }
@@ -1758,8 +1892,10 @@ ippWriteIO(void       *dst,              /* I - Destination */
        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(("ippWriteIO: op_status=%04x\n",
+                     ipp->request.any.op_status));
+       DEBUG_printf(("ippWriteIO: request_id=%d\n",
+                     ipp->request.any.request_id));
 
        /*
         * If blocking is disabled, stop here...
@@ -1791,7 +1927,8 @@ ippWriteIO(void       *dst,               /* I - Destination */
             if (attr->group_tag == IPP_TAG_ZERO)
              continue;
 
-            DEBUG_printf(("ippWriteIO: wrote group tag = %x\n", attr->group_tag));
+            DEBUG_printf(("ippWriteIO: wrote group tag=%x(%s)\n",
+                         attr->group_tag, ippTagString(attr->group_tag)));
            *bufptr++ = attr->group_tag;
          }
          else if (attr->group_tag == IPP_TAG_ZERO)
@@ -1815,15 +1952,21 @@ ippWriteIO(void       *dst,             /* I - Destination */
            * 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...
            */
 
-            DEBUG_printf(("ippWriteIO: writing value tag = %x\n", attr->value_tag));
-            DEBUG_printf(("ippWriteIO: writing name = %d, \'%s\'\n", n, attr->name));
+            DEBUG_printf(("ippWriteIO: writing value tag=%x(%s)\n",
+                         attr->value_tag, ippTagString(attr->value_tag)));
+            DEBUG_printf(("ippWriteIO: writing name=%d,\"%s\"\n", n,
+                         attr->name));
 
             *bufptr++ = attr->value_tag;
            *bufptr++ = n >> 8;
@@ -1838,19 +1981,25 @@ ippWriteIO(void       *dst,             /* I - Destination */
            * 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,
            * and empty name for the collection member attribute...
            */
 
-            DEBUG_printf(("ippWriteIO: writing value tag = %x\n",
+            DEBUG_printf(("ippWriteIO: writing value tag=%x(memberName)\n",
                          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(("ippWriteIO: writing name=%d,\"%s\"\n", n,
+                         attr->name));
+            DEBUG_printf(("ippWriteIO: writing value tag=%x(%s)\n",
+                         attr->value_tag, ippTagString(attr->value_tag)));
+            DEBUG_puts("ippWriteIO: writing name=0,\"\"\n");
 
             *bufptr++ = IPP_TAG_MEMBERNAME;
            *bufptr++ = 0;
@@ -1877,11 +2026,13 @@ ippWriteIO(void       *dst,             /* I - Destination */
                     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("ippWriteIO: Could not write IPP "
+                                "attribute...");
+                     ipp_buffer_release(buffer);
                      return (IPP_ERROR);
                    }
 
@@ -1921,11 +2072,13 @@ ippWriteIO(void       *dst,             /* I - Destination */
                     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("ippWriteIO: Could not write IPP "
+                                "attribute...");
+                     ipp_buffer_release(buffer);
                      return (IPP_ERROR);
                    }
 
@@ -1975,15 +2128,18 @@ ippWriteIO(void       *dst,             /* I - Destination */
                    * 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(("ippWriteIO: writing value tag=%x(%s)\n",
+                                 attr->value_tag,
+                                 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...");
+                       DEBUG_puts("ippWriteIO: Could not write IPP "
+                                  "attribute...");
+                       ipp_buffer_release(buffer);
                        return (IPP_ERROR);
                      }
 
@@ -2000,17 +2156,23 @@ ippWriteIO(void       *dst,             /* I - Destination */
                  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,
+                  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...");
+                     DEBUG_puts("ippWriteIO: Could not write IPP "
+                                "attribute...");
+                     ipp_buffer_release(buffer);
                      return (IPP_ERROR);
                    }
 
@@ -2043,11 +2205,13 @@ ippWriteIO(void       *dst,             /* I - Destination */
                     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("ippWriteIO: Could not write IPP "
+                                "attribute...");
+                     ipp_buffer_release(buffer);
                      return (IPP_ERROR);
                    }
 
@@ -2086,12 +2250,14 @@ ippWriteIO(void       *dst,             /* I - Destination */
                     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("ippWriteIO: Could not write IPP "
+                                "attribute...");
+                     ipp_buffer_release(buffer);
+                     return (IPP_ERROR);
                    }
 
                    bufptr = buffer;
@@ -2137,11 +2303,13 @@ ippWriteIO(void       *dst,             /* I - Destination */
                     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("ippWriteIO: Could not write IPP "
+                                "attribute...");
+                     ipp_buffer_release(buffer);
                      return (IPP_ERROR);
                    }
 
@@ -2194,11 +2362,13 @@ ippWriteIO(void       *dst,             /* I - Destination */
                    * 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("ippWriteIO: Could not write IPP "
+                                  "attribute...");
+                       ipp_buffer_release(buffer);
                        return (IPP_ERROR);
                      }
 
@@ -2228,14 +2398,21 @@ ippWriteIO(void       *dst,             /* I - Destination */
                  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...");
+                     DEBUG_puts("ippWriteIO: Could not write IPP "
+                                "attribute...");
+                     ipp_buffer_release(buffer);
                      return (IPP_ERROR);
                    }
 
@@ -2292,11 +2469,13 @@ ippWriteIO(void       *dst,             /* I - Destination */
                  * 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("ippWriteIO: Could not write IPP "
+                                "attribute...");
+                     ipp_buffer_release(buffer);
                      return (IPP_ERROR);
                    }
 
@@ -2324,7 +2503,9 @@ ippWriteIO(void       *dst,               /* I - Destination */
 
                   if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
                  {
-                   DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
+                   DEBUG_puts("ippWriteIO: Could not write IPP "
+                              "attribute...");
+                   ipp_buffer_release(buffer);
                    return (IPP_ERROR);
                  }
 
@@ -2336,8 +2517,13 @@ ippWriteIO(void       *dst,              /* I - Destination */
 
                   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;
 
@@ -2353,11 +2539,13 @@ ippWriteIO(void       *dst,             /* I - Destination */
                    * 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("ippWriteIO: Could not write IPP "
+                                  "attribute...");
+                       ipp_buffer_release(buffer);
                        return (IPP_ERROR);
                      }
 
@@ -2378,14 +2566,21 @@ ippWriteIO(void       *dst,             /* I - Destination */
 
                   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...");
+                     DEBUG_puts("ippWriteIO: Could not write IPP "
+                                "attribute...");
+                     ipp_buffer_release(buffer);
                      return (IPP_ERROR);
                    }
 
@@ -2413,6 +2608,7 @@ ippWriteIO(void       *dst,               /* I - Destination */
           if ((*cb)(dst, buffer, (int)(bufptr - buffer)) < 0)
          {
            DEBUG_puts("ippWriteIO: Could not write IPP attribute...");
+           ipp_buffer_release(buffer);
            return (IPP_ERROR);
          }
 
@@ -2452,6 +2648,7 @@ ippWriteIO(void       *dst,               /* I - Destination */
          if ((*cb)(dst, buffer, n) < 0)
          {
            DEBUG_puts("ippWriteIO: Could not write IPP end-tag...");
+           ipp_buffer_release(buffer);
            return (IPP_ERROR);
          }
 
@@ -2466,6 +2663,8 @@ ippWriteIO(void       *dst,               /* I - Destination */
         break; /* anti-compiler-warning-code */
   }
 
+  ipp_buffer_release(buffer);
+
   return (ipp->state);
 }
 
@@ -2481,9 +2680,9 @@ _ippAddAttr(ipp_t *ipp,                   /* I - IPP message */
   ipp_attribute_t      *attr;          /* New attribute */
 
 
-  DEBUG_printf(("_ippAddAttr(%p, %d)\n", ipp, num_values));
+  DEBUG_printf(("_ippAddAttr(ipp=%p, num_values=%d)\n", ipp, num_values));
 
-  if (ipp == NULL || num_values < 0)
+  if (!ipp || num_values < 0)
     return (NULL);
 
   attr = calloc(sizeof(ipp_attribute_t) +
@@ -2518,7 +2717,7 @@ _ippFreeAttr(ipp_attribute_t *attr)       /* I - Attribute to free */
   ipp_value_t  *value;                 /* Current value */
 
 
-  DEBUG_printf(("_ippFreeAttr(): %p\n", attr));
+  DEBUG_printf(("_ippFreeAttr(attr=%p)\n", attr));
 
   switch (attr->value_tag)
   {
@@ -2589,6 +2788,47 @@ _ippFreeAttr(ipp_attribute_t *attr)      /* I - Attribute to free */
 }
 
 
+/*
+ * '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.
  */
@@ -2908,5 +3148,5 @@ _ipp_free_attr(ipp_attribute_t *attr)     /* I - Attribute to free */
 
 
 /*
- * End of "$Id: ipp.c 6649 2007-07-11 21:46:42Z mike $".
+ * End of "$Id: ipp.c 7847 2008-08-19 04:22:14Z mike $".
  */