Various updates so pycups builds against cups-1.6
Patch obtained from upstream git by
# git diff 428aeeb629fcec07c59c35b896a2e2605d1c724e..fd985079fd7075cfc7148918bd48eeafa143cf6b

diff --git a/COPYING b/COPYING
index 60549be..d159169 100644
--- a/COPYING
+++ b/COPYING
@@ -1,12 +1,12 @@
-		    GNU GENERAL PUBLIC LICENSE
-		       Version 2, June 1991
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
 
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
-                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  Everyone is permitted to copy and distribute verbatim copies
  of this license document, but changing it is not allowed.
 
-			    Preamble
+                            Preamble
 
   The licenses for most software are designed to take away your
 freedom to share and change it.  By contrast, the GNU General Public
@@ -15,7 +15,7 @@ software--to make sure the software is free for all its users.  This
 General Public License applies to most of the Free Software
 Foundation's software and to any other program whose authors commit to
 using it.  (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.)  You can apply it to
+the GNU Lesser General Public License instead.)  You can apply it to
 your programs, too.
 
   When we speak of free software, we are referring to freedom, not
@@ -55,8 +55,8 @@ patent must be licensed for everyone's free use or not licensed at all.
 
   The precise terms and conditions for copying, distribution and
 modification follow.
-
-		    GNU GENERAL PUBLIC LICENSE
+
+                    GNU GENERAL PUBLIC LICENSE
    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
 
   0. This License applies to any program or other work which contains
@@ -110,7 +110,7 @@ above, provided that you also meet all of these conditions:
     License.  (Exception: if the Program itself is interactive but
     does not normally print such an announcement, your work based on
     the Program is not required to print an announcement.)
-
+
 These requirements apply to the modified work as a whole.  If
 identifiable sections of that work are not derived from the Program,
 and can be reasonably considered independent and separate works in
@@ -168,7 +168,7 @@ access to copy from a designated place, then offering equivalent
 access to copy the source code from the same place counts as
 distribution of the source code, even though third parties are not
 compelled to copy the source along with the object code.
-
+
   4. You may not copy, modify, sublicense, or distribute the Program
 except as expressly provided under this License.  Any attempt
 otherwise to copy, modify, sublicense or distribute the Program is
@@ -225,7 +225,7 @@ impose that choice.
 
 This section is intended to make thoroughly clear what is believed to
 be a consequence of the rest of this License.
-
+
   8. If the distribution and/or use of the Program is restricted in
 certain countries either by patents or by copyrighted interfaces, the
 original copyright holder who places the Program under this License
@@ -255,7 +255,7 @@ make exceptions for this.  Our decision will be guided by the two goals
 of preserving the free status of all derivatives of our free software and
 of promoting the sharing and reuse of software generally.
 
-			    NO WARRANTY
+                            NO WARRANTY
 
   11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
 FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
@@ -277,9 +277,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
 PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
 POSSIBILITY OF SUCH DAMAGES.
 
-		     END OF TERMS AND CONDITIONS
-
-	    How to Apply These Terms to Your New Programs
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
 
   If you develop a new program, and you want it to be of the greatest
 possible use to the public, the best way to achieve this is to make it
@@ -291,7 +291,7 @@ convey the exclusion of warranty; and each file should have at least
 the "copyright" line and a pointer to where the full notice is found.
 
     <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) 19yy  <name of author>
+    Copyright (C) <year>  <name of author>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -303,17 +303,16 @@ the "copyright" line and a pointer to where the full notice is found.
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.
 
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
 Also add information on how to contact you by electronic and paper mail.
 
 If the program is interactive, make it output a short notice like this
 when it starts in an interactive mode:
 
-    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision version 69, Copyright (C) year name of author
     Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
     This is free software, and you are welcome to redistribute it
     under certain conditions; type `show c' for details.
@@ -336,5 +335,5 @@ necessary.  Here is a sample; alter the names:
 This General Public License does not permit incorporating your program into
 proprietary programs.  If your program is a subroutine library, you may
 consider it more useful to permit linking proprietary applications with the
-library.  If this is what you want to do, use the GNU Library General
+library.  If this is what you want to do, use the GNU Lesser General
 Public License instead of this License.
diff --git a/ChangeLog b/ChangeLog
index 0a16470..22fdb16 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2012-03-28  Tim Waugh  <twaugh@redhat.com>
+
+	* cupsmodule.c: Define all constants regardless of which
+	version of CUPS is built against.
+
+2012-03-22  Tim Waugh  <twaugh@redhat.com>
+
+	* cupsppd.c (PPD_dealloc): Add missing NULL check for
+	debugging message (Ubuntu #951001).  Patch from Till Kamppeter.
+
 2012-03-06  Tim Waugh  <twaugh@redhat.com>
 
 	* setup.py: Version 1.9.61.
diff --git a/cupsconnection.c b/cupsconnection.c
index 37820a9..5c9d1a5 100644
--- a/cupsconnection.c
+++ b/cupsconnection.c
@@ -15,7 +15,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
 #include "cupsconnection.h"
@@ -477,10 +477,10 @@ do_printer_request (Connection *self, PyObject *args, PyObject *kwds,
     return NULL;
   }
 
-  if (!answer || answer->request.status.status_code > IPP_OK_CONFLICT) {
+  if (!answer || ippGetStatusCode (answer) > IPP_OK_CONFLICT) {
     set_ipp_error (answer ?
-		   answer->request.status.status_code :
-		   cupsLastError ());
+		    ippGetStatusCode (answer) :
+                  cupsLastError ());
     if (answer)
       ippDelete (answer);
     debugprintf("<- do_printer_request (error)\n");
@@ -562,7 +562,11 @@ PyObject_from_attr_value (ipp_attribute_t *attr, int i)
 {
   PyObject *val = NULL;
   char unknown[100];
-  switch (attr->value_tag) {
+  int lower, upper;
+  int xres, yres;
+  ipp_res_t units;
+
+  switch (ippGetValueTag(attr)) {
   case IPP_TAG_NAME:
   case IPP_TAG_TEXT:
   case IPP_TAG_KEYWORD:
@@ -570,19 +574,20 @@ PyObject_from_attr_value (ipp_attribute_t *attr, int i)
   case IPP_TAG_CHARSET:
   case IPP_TAG_MIMETYPE:
   case IPP_TAG_LANGUAGE:
-    val = PyObj_from_UTF8 (attr->values[i].string.text);
+    val = PyObj_from_UTF8 (ippGetString (attr, i, NULL));
     break;
   case IPP_TAG_INTEGER:
   case IPP_TAG_ENUM:
-    val = PyInt_FromLong (attr->values[i].integer);
+    val = PyInt_FromLong (ippGetInteger (attr, i));
     break;
   case IPP_TAG_BOOLEAN:
-    val = PyBool_FromLong (attr->values[i].integer);
+    val = PyBool_FromLong (ippGetInteger (attr, i));
     break;
   case IPP_TAG_RANGE:
+    lower = ippGetRange (attr, i, &upper);
     val = Py_BuildValue ("(ii)",
-			 attr->values[i].range.lower,
-			 attr->values[i].range.upper);
+			 lower,
+			 upper);
     break;
   case IPP_TAG_NOVALUE:
     Py_INCREF (Py_None);
@@ -594,14 +599,15 @@ PyObject_from_attr_value (ipp_attribute_t *attr, int i)
     val = PyString_FromString ("(IPP_TAG_DATE)");
     break;
   case IPP_TAG_RESOLUTION:
+    xres = ippGetResolution(attr, i, &yres, &units);
     val = Py_BuildValue ("(iii)",
-			 attr->values[i].resolution.xres,
-			 attr->values[i].resolution.yres,
-			 attr->values[i].resolution.units);
+			 xres,
+			 yres,
+			 units);
     break;
   default:
     snprintf (unknown, sizeof (unknown),
-	      "(unknown IPP value tag 0x%x)", attr->value_tag);
+	      "(unknown IPP value tag 0x%x)", ippGetValueTag(attr));
     val = PyString_FromString (unknown);
     break;
   }
@@ -615,7 +621,7 @@ PyList_from_attr_values (ipp_attribute_t *attr)
   PyObject *list = PyList_New (0);
   int i;
   debugprintf ("-> PyList_from_attr_values()\n");
-  for (i = 0; i < attr->num_values; i++) {
+  for (i = 0; i < ippGetCount (attr); i++) {
     PyObject *val = PyObject_from_attr_value (attr, i);
     if (val) {
       PyList_Append (list, val);
@@ -657,8 +663,8 @@ Connection_getPrinters (Connection *self)
   Connection_begin_allow_threads (self);
   answer = cupsDoRequest (self->http, request, "/");
   Connection_end_allow_threads (self);
-  if (!answer || answer->request.status.status_code > IPP_OK_CONFLICT) {
-    if (answer && answer->request.status.status_code == IPP_NOT_FOUND) {
+  if (!answer || ippGetStatusCode (answer) > IPP_OK_CONFLICT) {
+    if (answer && ippGetStatusCode (answer) == IPP_NOT_FOUND) {
       // No printers.
       debugprintf ("<- Connection_getPrinters() = {} (no printers)\n");
       ippDelete (answer);
@@ -666,7 +672,7 @@ Connection_getPrinters (Connection *self)
     }
 
     set_ipp_error (answer ?
-		   answer->request.status.status_code :
+		   ippGetStatusCode (answer) :
 		   cupsLastError ());
     if (answer)
       ippDelete (answer);
@@ -675,71 +681,71 @@ Connection_getPrinters (Connection *self)
   }
 
   result = PyDict_New ();
-  for (attr = answer->attrs; attr; attr = attr->next) {
+  for (attr = ippFirstAttribute (answer); attr; attr = ippNextAttribute (answer)) {
     PyObject *dict;
     char *printer = NULL;
 
-    while (attr && attr->group_tag != IPP_TAG_PRINTER)
-      attr = attr->next;
+    while (attr && ippGetGroupTag (attr) != IPP_TAG_PRINTER)
+      attr = ippNextAttribute (answer);
 
     if (!attr)
       break;
 
     dict = PyDict_New ();
-    for (; attr && attr->group_tag == IPP_TAG_PRINTER;
-	 attr = attr->next) {
+    for (; attr && ippGetGroupTag (attr) == IPP_TAG_PRINTER;
+	 attr = ippNextAttribute (answer)) {
       PyObject *val = NULL;
 
-      debugprintf ("Attribute: %s\n", attr->name);
-      if (!strcmp (attr->name, "printer-name") &&
-	  attr->value_tag == IPP_TAG_NAME)
-	printer = attr->values[0].string.text;
-      else if ((!strcmp (attr->name, "printer-type") ||
-		!strcmp (attr->name, "printer-state")) &&
-	       attr->value_tag == IPP_TAG_ENUM) {
-	int ptype = attr->values[0].integer;
+      debugprintf ("Attribute: %s\n", ippGetName (attr));
+      if (!strcmp (ippGetName (attr), "printer-name") &&
+	  ippGetValueTag (attr) == IPP_TAG_NAME)
+	printer = (char *) ippGetString (attr, 0, NULL);
+      else if ((!strcmp (ippGetName (attr), "printer-type") ||
+		!strcmp (ippGetName (attr), "printer-state")) &&
+	       ippGetValueTag (attr) == IPP_TAG_ENUM) {
+	int ptype = ippGetInteger (attr, 0);
 	val = PyInt_FromLong (ptype);
       }
-      else if ((!strcmp (attr->name,
+      else if ((!strcmp (ippGetName (attr),
 			 "printer-make-and-model") ||
-		!strcmp (attr->name, "printer-info") ||
-		!strcmp (attr->name, "printer-location") ||
-		!strcmp (attr->name, "printer-state-message")) &&
-	       attr->value_tag == IPP_TAG_TEXT) {
-	val = PyObj_from_UTF8 (attr->values[0].string.text);
+		!strcmp (ippGetName (attr), "printer-info") ||
+		!strcmp (ippGetName (attr), "printer-location") ||
+		!strcmp (ippGetName (attr), "printer-state-message")) &&
+	       ippGetValueTag (attr) == IPP_TAG_TEXT) {
+	val = PyObj_from_UTF8 (ippGetString (attr, 0, NULL));
       }
-      else if (!strcmp (attr->name,
+      else if (!strcmp (ippGetName (attr),
 			"printer-state-reasons") &&
-	       attr->value_tag == IPP_TAG_KEYWORD) {
+	       ippGetValueTag (attr) == IPP_TAG_KEYWORD) {
 	val = PyList_from_attr_values (attr);
       }
-      else if (!strcmp (attr->name,
+      else if (!strcmp (ippGetName (attr),
 			"printer-is-accepting-jobs") &&
-	       attr->value_tag == IPP_TAG_BOOLEAN) {
-	int b = attr->values[0].boolean;
+	       ippGetValueTag (attr) == IPP_TAG_BOOLEAN) {
+	int b = ippGetBoolean (attr, 0);
 	val = PyInt_FromLong (b);
       }
-      else if ((!strcmp (attr->name,
+      else if ((!strcmp (ippGetName (attr),
 			 "printer-up-time") ||
-		!strcmp (attr->name,
+		!strcmp (ippGetName (attr),
 			 "queued-job-count")) &&
-	       attr->value_tag == IPP_TAG_INTEGER) {
-	int u = attr->values[0].integer;
+	       ippGetValueTag (attr) == IPP_TAG_INTEGER) {
+	int u = ippGetInteger (attr, 0);
 	val = PyInt_FromLong (u);
       }
-      else if ((!strcmp (attr->name, "device-uri") ||
-		!strcmp (attr->name, "printer-uri-supported")) &&
-	       attr->value_tag == IPP_TAG_URI) {
-	val = PyObj_from_UTF8 (attr->values[0].string.text);
+      else if ((!strcmp (ippGetName (attr), "device-uri") ||
+		!strcmp (ippGetName (attr), "printer-uri-supported")) &&
+	       ippGetValueTag (attr) == IPP_TAG_URI) {
+	val = PyObj_from_UTF8 (ippGetString (attr, 0, NULL));
       }
-      else if (!strcmp (attr->name, "printer-is-shared") &&
-	       attr->value_tag == IPP_TAG_BOOLEAN) {
-	val = PyBool_FromLong (attr->values[0].boolean);
+      else if (!strcmp (ippGetName (attr), "printer-is-shared") &&
+	       ippGetValueTag (attr) == IPP_TAG_BOOLEAN) {
+	val = PyBool_FromLong (ippGetBoolean (attr, 0));
       }
 
       if (val) {
-	debugprintf ("Added %s to dict\n", attr->name);
-	PyDict_SetItemString (dict, attr->name, val);
+	debugprintf ("Added %s to dict\n", ippGetName (attr));
+	PyDict_SetItemString (dict, ippGetName (attr), val);
 	Py_DECREF (val);
       }
     }
@@ -780,8 +786,8 @@ Connection_getClasses (Connection *self)
   Connection_begin_allow_threads (self);
   answer = cupsDoRequest (self->http, request, "/");
   Connection_end_allow_threads (self);
-  if (!answer || answer->request.status.status_code > IPP_OK_CONFLICT) {
-    if (answer && answer->request.status.status_code == IPP_NOT_FOUND) {
+  if (!answer || ippGetStatusCode (answer) > IPP_OK_CONFLICT) {
+    if (answer && ippGetStatusCode (answer) == IPP_NOT_FOUND) {
       // No classes.
       debugprintf ("<- Connection_getClasses() = {} (no classes)\n");
       ippDelete (answer);
@@ -789,7 +795,7 @@ Connection_getClasses (Connection *self)
     }
 
     set_ipp_error (answer ?
-		   answer->request.status.status_code :
+		   ippGetStatusCode (answer) :
 		   cupsLastError ());
     if (answer)
       ippDelete (answer);
@@ -798,28 +804,28 @@ Connection_getClasses (Connection *self)
   }
 
   result = PyDict_New ();
-  for (attr = answer->attrs; attr; attr = attr->next) {
+  for (attr = ippFirstAttribute (answer); attr; attr = ippNextAttribute (answer)) {
     PyObject *members = NULL;
     char *classname = NULL;
     char *printer_uri = NULL;
 
-    while (attr && attr->group_tag != IPP_TAG_PRINTER)
-      attr = attr->next;
+    while (attr && ippGetGroupTag (attr) != IPP_TAG_PRINTER)
+      attr = ippNextAttribute (answer);
 
     if (!attr)
       break;
 
-     for (; attr && attr->group_tag == IPP_TAG_PRINTER;
-	 attr = attr->next) {
-      debugprintf ("Attribute: %s\n", attr->name);
-      if (!strcmp (attr->name, "printer-name") &&
-	  attr->value_tag == IPP_TAG_NAME)
-	classname = attr->values[0].string.text;
-      else if (!strcmp (attr->name, "printer-uri-supported") &&
-	       attr->value_tag == IPP_TAG_URI)
-	printer_uri = attr->values[0].string.text;
-      else if (!strcmp (attr->name, "member-names") &&
-	       attr->value_tag == IPP_TAG_NAME) {
+     for (; attr && ippGetGroupTag (attr) == IPP_TAG_PRINTER;
+	 attr = ippNextAttribute (answer)) {
+      debugprintf ("Attribute: %s\n", ippGetName (attr));
+      if (!strcmp (ippGetName (attr), "printer-name") &&
+	  ippGetValueTag (attr) == IPP_TAG_NAME)
+	classname = (char *) ippGetString (attr, 0, NULL);
+      else if (!strcmp (ippGetName (attr), "printer-uri-supported") &&
+	       ippGetValueTag (attr) == IPP_TAG_URI)
+	printer_uri = (char *) ippGetString (attr, 0, NULL);
+      else if (!strcmp (ippGetName (attr), "member-names") &&
+	       ippGetValueTag (attr) == IPP_TAG_NAME) {
 	Py_XDECREF (members);
 	members = PyList_from_attr_values (attr);
       }
@@ -1057,9 +1063,9 @@ do_getPPDs (Connection *self, PyObject *args, PyObject *kwds, int all_lists)
   Connection_begin_allow_threads (self);
   answer = cupsDoRequest (self->http, request, "/");
   Connection_end_allow_threads (self);
-  if (!answer || answer->request.status.status_code > IPP_OK_CONFLICT) {
+  if (!answer || ippGetStatusCode (answer) > IPP_OK_CONFLICT) {
     set_ipp_error (answer ?
-		   answer->request.status.status_code :
+		   ippGetStatusCode (answer) :
 		   cupsLastError ());
     if (answer)
       ippDelete (answer);
@@ -1068,24 +1074,24 @@ do_getPPDs (Connection *self, PyObject *args, PyObject *kwds, int all_lists)
   }
 
   result = PyDict_New ();
-  for (attr = answer->attrs; attr; attr = attr->next) {
+  for (attr = ippFirstAttribute (answer); attr; attr = ippNextAttribute (answer)) {
     PyObject *dict;
     char *ppdname = NULL;
 
-    while (attr && attr->group_tag != IPP_TAG_PRINTER)
-      attr = attr->next;
+    while (attr && ippGetGroupTag (attr) != IPP_TAG_PRINTER)
+      attr = ippNextAttribute (answer);
 
     if (!attr)
       break;
 
     dict = PyDict_New ();
-    for (; attr && attr->group_tag == IPP_TAG_PRINTER;
-	 attr = attr->next) {
+    for (; attr && ippGetGroupTag (attr) == IPP_TAG_PRINTER;
+	 attr = ippNextAttribute (answer)) {
       PyObject *val = NULL;
-      debugprintf ("Attribute: %s\n", attr->name);
-      if (!strcmp (attr->name, "ppd-name") &&
-	  attr->value_tag == IPP_TAG_NAME)
-	ppdname = attr->values[0].string.text;
+      debugprintf ("Attribute: %s\n", ippGetName (attr));
+      if (!strcmp (ippGetName (attr), "ppd-name") &&
+	  ippGetValueTag (attr) == IPP_TAG_NAME)
+	ppdname = (char *) ippGetString (attr, 0, NULL);
       else {
 	if (all_lists)
 	  val = PyList_from_attr_values (attr);
@@ -1093,8 +1099,8 @@ do_getPPDs (Connection *self, PyObject *args, PyObject *kwds, int all_lists)
 	  val = PyObject_from_attr_value (attr, 0);
 
 	if (val) {
-	  debugprintf ("Adding %s to ppd dict\n", attr->name);
-	  PyDict_SetItemString (dict, attr->name, val);
+	  debugprintf ("Adding %s to ppd dict\n", ippGetName (attr));
+	  PyDict_SetItemString (dict, ippGetName (attr), val);
 	  Py_DECREF (val);
 	}
       }
@@ -1201,10 +1207,10 @@ Connection_getDocument (Connection *self, PyObject *args)
   Connection_end_allow_threads (self);
 
   close (fd);
-  if (!answer || answer->request.status.status_code > IPP_OK_CONFLICT) {
+  if (!answer || ippGetStatusCode (answer) > IPP_OK_CONFLICT) {
     unlink (docfilename);
     set_ipp_error (answer ?
-		   answer->request.status.status_code :
+		   ippGetStatusCode (answer) :
 		   cupsLastError ());
     if (answer)
       ippDelete (answer);
@@ -1214,11 +1220,11 @@ Connection_getDocument (Connection *self, PyObject *args)
 
   if ((attr = ippFindAttribute (answer, "document-format",
 				IPP_TAG_MIMETYPE)) != NULL)
-    format = attr->values[0].string.text;
+    format = ippGetString (attr, 0, NULL);
 
   if ((attr = ippFindAttribute (answer, "document-name",
 				IPP_TAG_NAME)) != NULL)
-    name = attr->values[0].string.text;
+    name = ippGetString (attr, 0, NULL);
 
   dict = PyDict_New ();
 
@@ -1362,9 +1368,9 @@ Connection_getDevices (Connection *self, PyObject *args, PyObject *kwds)
   Connection_begin_allow_threads (self);
   answer = cupsDoRequest (self->http, request, "/");
   Connection_end_allow_threads (self);
-  if (!answer || answer->request.status.status_code > IPP_OK_CONFLICT) {
+  if (!answer || ippGetStatusCode (answer) > IPP_OK_CONFLICT) {
     set_ipp_error (answer ?
-		   answer->request.status.status_code :
+		   ippGetStatusCode (answer) :
 		   cupsLastError ());
     if (answer)
       ippDelete (answer);
@@ -1373,31 +1379,31 @@ Connection_getDevices (Connection *self, PyObject *args, PyObject *kwds)
   }
 
   result = PyDict_New ();
-  for (attr = answer->attrs; attr; attr = attr->next) {
+  for (attr = ippFirstAttribute (answer); attr; attr = ippNextAttribute (answer)) {
     PyObject *dict;
     char *device_uri = NULL;
 
-    while (attr && attr->group_tag != IPP_TAG_PRINTER)
-      attr = attr->next;
+    while (attr && ippGetGroupTag (attr) != IPP_TAG_PRINTER)
+      attr = ippNextAttribute (answer);
 
     if (!attr)
       break;
 
     dict = PyDict_New ();
-    for (; attr && attr->group_tag == IPP_TAG_PRINTER;
-	 attr = attr->next) {
+    for (; attr && ippGetGroupTag (attr) == IPP_TAG_PRINTER;
+	 attr = ippNextAttribute (answer)) {
       PyObject *val = NULL;
 
-      debugprintf ("Attribute: %s\n", attr->name);
-      if (!strcmp (attr->name, "device-uri") &&
-	  attr->value_tag == IPP_TAG_URI)
-	device_uri = attr->values[0].string.text;
+      debugprintf ("Attribute: %s\n", ippGetName (attr));
+      if (!strcmp (ippGetName (attr), "device-uri") &&
+	  ippGetValueTag (attr) == IPP_TAG_URI)
+	device_uri = (char *) ippGetString (attr, 0, NULL);
       else
 	val = PyObject_from_attr_value (attr, 0);
 
       if (val) {
-	debugprintf ("Adding %s to device dict\n", attr->name);
-	PyDict_SetItemString (dict, attr->name, val);
+	debugprintf ("Adding %s to device dict\n", ippGetName (attr));
+	PyDict_SetItemString (dict, ippGetName (attr), val);
 	Py_DECREF (val);
       }
     }
@@ -1523,9 +1529,9 @@ Connection_getJobs (Connection *self, PyObject *args, PyObject *kwds)
   Connection_begin_allow_threads (self);
   answer = cupsDoRequest (self->http, request, "/");
   Connection_end_allow_threads (self);
-  if (!answer || answer->request.status.status_code > IPP_OK_CONFLICT) {
+  if (!answer || ippGetStatusCode (answer) > IPP_OK_CONFLICT) {
     set_ipp_error (answer ?
-		   answer->request.status.status_code :
+		   ippGetStatusCode (answer) :
 		   cupsLastError ());
     if (answer)
       ippDelete (answer);
@@ -1534,56 +1540,56 @@ Connection_getJobs (Connection *self, PyObject *args, PyObject *kwds)
   }
 
   result = PyDict_New ();
-  for (attr = answer->attrs; attr; attr = attr->next) {
+  for (attr = ippFirstAttribute (answer); attr; attr = ippNextAttribute (answer)) {
     PyObject *dict;
     int job_id = -1;
 
-    while (attr && attr->group_tag != IPP_TAG_JOB)
-      attr = attr->next;
+    while (attr && ippGetGroupTag (attr) != IPP_TAG_JOB)
+      attr = ippNextAttribute (answer);
 
     if (!attr)
       break;
 
     dict = PyDict_New ();
-    for (; attr && attr->group_tag == IPP_TAG_JOB;
-	 attr = attr->next) {
+    for (; attr && ippGetGroupTag (attr) == IPP_TAG_JOB;
+	 attr = ippNextAttribute (answer)) {
       PyObject *val = NULL;
 
-      debugprintf ("Attribute: %s\n", attr->name);
-      if (!strcmp (attr->name, "job-id") &&
-	  attr->value_tag == IPP_TAG_INTEGER)
-	job_id = attr->values[0].integer;
-      else if (((!strcmp (attr->name, "job-k-octets") ||
-		 !strcmp (attr->name, "job-priority") ||
-		 !strcmp (attr->name, "time-at-creation") ||
-		 !strcmp (attr->name, "time-at-processing") ||
-		 !strcmp (attr->name, "time-at-completed") ||
-		 !strcmp (attr->name, "job-media-sheets") ||
-		 !strcmp (attr->name, "job-media-sheets-completed")) &&
-		attr->value_tag == IPP_TAG_INTEGER) ||
-	       (!strcmp (attr->name, "job-state") &&
-		attr->value_tag == IPP_TAG_ENUM))
-	val = PyInt_FromLong (attr->values[0].integer);
-      else if ((!strcmp (attr->name, "job-name") &&
-		attr->value_tag == IPP_TAG_NAME) ||
-	       (!strcmp (attr->name, "job-originating-user-name") &&
-		attr->value_tag == IPP_TAG_NAME) ||
-	       (!strcmp (attr->name, "job-printer-uri") &&
-		attr->value_tag == IPP_TAG_URI))
-	val = PyObj_from_UTF8 (attr->values[0].string.text);
-      else if (!strcmp (attr->name, "job-preserved") &&
-	       attr->value_tag == IPP_TAG_BOOLEAN)
-	val = PyBool_FromLong (attr->values[0].integer);
+      debugprintf ("Attribute: %s\n", ippGetName (attr));
+      if (!strcmp (ippGetName (attr), "job-id") &&
+	  ippGetValueTag (attr) == IPP_TAG_INTEGER)
+	job_id = ippGetInteger (attr, 0);
+      else if (((!strcmp (ippGetName (attr), "job-k-octets") ||
+		 !strcmp (ippGetName (attr), "job-priority") ||
+		 !strcmp (ippGetName (attr), "time-at-creation") ||
+		 !strcmp (ippGetName (attr), "time-at-processing") ||
+		 !strcmp (ippGetName (attr), "time-at-completed") ||
+		 !strcmp (ippGetName (attr), "job-media-sheets") ||
+		 !strcmp (ippGetName (attr), "job-media-sheets-completed")) &&
+		ippGetValueTag (attr) == IPP_TAG_INTEGER) ||
+	       (!strcmp (ippGetName (attr), "job-state") &&
+		ippGetValueTag (attr) == IPP_TAG_ENUM))
+	val = PyInt_FromLong (ippGetInteger (attr, 0));
+      else if ((!strcmp (ippGetName (attr), "job-name") &&
+		ippGetValueTag (attr) == IPP_TAG_NAME) ||
+	       (!strcmp (ippGetName (attr), "job-originating-user-name") &&
+		ippGetValueTag (attr) == IPP_TAG_NAME) ||
+	       (!strcmp (ippGetName (attr), "job-printer-uri") &&
+		ippGetValueTag (attr) == IPP_TAG_URI))
+	val = PyObj_from_UTF8 (ippGetString (attr, 0, NULL));
+      else if (!strcmp (ippGetName (attr), "job-preserved") &&
+	       ippGetValueTag (attr) == IPP_TAG_BOOLEAN)
+	val = PyBool_FromLong (ippGetInteger (attr, 0));
       else {
-	if (attr->num_values > 1)
+	if (ippGetCount (attr) > 1)
 	  val = PyList_from_attr_values (attr);
 	else
 	  val = PyObject_from_attr_value (attr, 0);
       }
 
       if (val) {
-	debugprintf ("Adding %s to job dict\n", attr->name);
-	PyDict_SetItemString (dict, attr->name, val);
+	debugprintf ("Adding %s to job dict\n", ippGetName (attr));
+	PyDict_SetItemString (dict, ippGetName (attr), val);
 	Py_DECREF (val);
       }
     }
@@ -1643,9 +1649,9 @@ Connection_getJobAttributes (Connection *self, PyObject *args, PyObject *kwds)
   Connection_end_allow_threads (self);
   if (requested_attrs)
     free_requested_attrs (n_attrs, attrs);
-  if (!answer || answer->request.status.status_code > IPP_OK_CONFLICT) {
+  if (!answer || ippGetStatusCode (answer) > IPP_OK_CONFLICT) {
     set_ipp_error (answer ?
-		   answer->request.status.status_code :
+		   ippGetStatusCode (answer) :
 		   cupsLastError ());
     if (answer)
       ippDelete (answer);
@@ -1654,12 +1660,12 @@ Connection_getJobAttributes (Connection *self, PyObject *args, PyObject *kwds)
   }
 
   result = PyDict_New ();
-  for (attr = answer->attrs; attr; attr = attr->next) {
+  for (attr = ippFirstAttribute (answer); attr; attr = ippNextAttribute (answer)) {
     PyObject *obj;
 
-    debugprintf ("Attr: %s\n", attr->name);
-    if (attr->num_values > 1 ||
-	!strcmp (attr->name, "job-printer-state-reasons"))
+    debugprintf ("Attr: %s\n", ippGetName (attr));
+    if (ippGetCount (attr) > 1 ||
+	!strcmp (ippGetName (attr), "job-printer-state-reasons"))
       obj = PyList_from_attr_values (attr);
     else
       obj = PyObject_from_attr_value (attr, 0);
@@ -1668,7 +1674,7 @@ Connection_getJobAttributes (Connection *self, PyObject *args, PyObject *kwds)
       // Can't represent this.
       continue;
 
-    PyDict_SetItemString (result, attr->name, obj);
+    PyDict_SetItemString (result, ippGetName (attr), obj);
     Py_DECREF (obj);
   }
 
@@ -1701,9 +1707,9 @@ Connection_cancelJob (Connection *self, PyObject *args, PyObject *kwds)
   Connection_begin_allow_threads (self);
   answer = cupsDoRequest (self->http, request, "/jobs/");
   Connection_end_allow_threads (self);
-  if (!answer || answer->request.status.status_code > IPP_OK_CONFLICT) {
+  if (!answer || ippGetStatusCode (answer) > IPP_OK_CONFLICT) {
     set_ipp_error (answer ?
-		   answer->request.status.status_code :
+		   ippGetStatusCode (answer) :
 		   cupsLastError ());
     if (answer)
       ippDelete (answer);
@@ -1774,7 +1780,7 @@ Connection_cancelAllJobs (Connection *self, PyObject *args, PyObject *kwds)
     Connection_begin_allow_threads (self);
     answer = cupsDoRequest (self->http, request, "/admin/");
     Connection_end_allow_threads (self);
-    if (answer && answer->request.status.status_code == IPP_NOT_POSSIBLE) {
+    if (answer && ippGetStatusCode (answer) == IPP_NOT_POSSIBLE) {
       ippDelete (answer);
       if (uriobj)
 	break;
@@ -1790,9 +1796,9 @@ Connection_cancelAllJobs (Connection *self, PyObject *args, PyObject *kwds)
   if (uriobj)
     free (uri);
 
-  if (!answer || answer->request.status.status_code > IPP_OK_CONFLICT) {
+  if (!answer || ippGetStatusCode (answer) > IPP_OK_CONFLICT) {
     set_ipp_error (answer ?
-		   answer->request.status.status_code :
+		   ippGetStatusCode (answer) :
 		   cupsLastError ());
     if (answer)
       ippDelete (answer);
@@ -1864,9 +1870,9 @@ Connection_moveJob (Connection *self, PyObject *args, PyObject *kwds)
   Connection_begin_allow_threads (self);
   answer = cupsDoRequest (self->http, request, "/jobs");
   Connection_end_allow_threads (self);
-  if (!answer || answer->request.status.status_code > IPP_OK_CONFLICT) {
+  if (!answer || ippGetStatusCode (answer) > IPP_OK_CONFLICT) {
     set_ipp_error (answer ?
-		   answer->request.status.status_code :
+		   ippGetStatusCode (answer) :
 		   cupsLastError ());
     if (answer)
       ippDelete (answer);
@@ -1931,9 +1937,9 @@ Connection_authenticateJob (Connection *self, PyObject *args)
   Connection_begin_allow_threads (self);
   answer = cupsDoRequest (self->http, request, "/jobs/");
   Connection_end_allow_threads (self);
-  if (!answer || answer->request.status.status_code > IPP_OK_CONFLICT) {
+  if (!answer || ippGetStatusCode (answer) > IPP_OK_CONFLICT) {
     set_ipp_error (answer ?
-		   answer->request.status.status_code :
+		   ippGetStatusCode (answer) :
 		   cupsLastError ());
     if (answer)
       ippDelete (answer);
@@ -1977,9 +1983,9 @@ Connection_setJobHoldUntil (Connection *self, PyObject *args)
   Connection_begin_allow_threads (self);
   answer = cupsDoRequest (self->http, request, "/jobs/");
   Connection_end_allow_threads (self);
-  if (!answer || answer->request.status.status_code > IPP_OK_CONFLICT) {
+  if (!answer || ippGetStatusCode (answer) > IPP_OK_CONFLICT) {
     set_ipp_error (answer ?
-		   answer->request.status.status_code :
+		   ippGetStatusCode (answer) :
 		   cupsLastError ());
     if (answer)
       ippDelete (answer);
@@ -2017,9 +2023,9 @@ Connection_restartJob (Connection *self, PyObject *args, PyObject *kwds)
   Connection_begin_allow_threads (self);
   answer = cupsDoRequest (self->http, request, "/jobs/");
   Connection_end_allow_threads (self);
-  if (!answer || answer->request.status.status_code > IPP_OK_CONFLICT) {
+  if (!answer || ippGetStatusCode (answer) > IPP_OK_CONFLICT) {
     set_ipp_error (answer ?
-		   answer->request.status.status_code :
+		   ippGetStatusCode (answer) :
 		   cupsLastError ());
     if (answer)
       ippDelete (answer);
@@ -2314,9 +2320,9 @@ Connection_addPrinter (Connection *self, PyObject *args, PyObject *kwds)
     return NULL;
   }
 
-  if (!answer || answer->request.status.status_code > IPP_OK_CONFLICT) {
+  if (!answer || ippGetStatusCode (answer) > IPP_OK_CONFLICT) {
     set_ipp_error (answer ?
-		   answer->request.status.status_code :
+		   ippGetStatusCode (answer) :
 		   cupsLastError ());
     if (answer)
       ippDelete (answer);
@@ -2364,9 +2370,9 @@ Connection_setPrinterDevice (Connection *self, PyObject *args)
     return NULL;
   }
 
-  if (!answer || answer->request.status.status_code > IPP_OK_CONFLICT) {
+  if (!answer || ippGetStatusCode (answer) > IPP_OK_CONFLICT) {
     set_ipp_error (answer ?
-		   answer->request.status.status_code :
+		   ippGetStatusCode (answer) :
 		   cupsLastError ());
     if (answer)
       ippDelete (answer);
@@ -2411,7 +2417,7 @@ Connection_setPrinterInfo (Connection *self, PyObject *args)
       return NULL;
     }
 
-    if (answer && answer->request.status.status_code == IPP_NOT_POSSIBLE) {
+    if (answer && ippGetStatusCode (answer) == IPP_NOT_POSSIBLE) {
       // Perhaps it's a class, not a printer.
       ippDelete (answer);
       request = add_modify_class_request (name);
@@ -2420,9 +2426,9 @@ Connection_setPrinterInfo (Connection *self, PyObject *args)
 
   free (name);
   free (info);
-  if (!answer || answer->request.status.status_code > IPP_OK_CONFLICT) {
+  if (!answer || ippGetStatusCode (answer) > IPP_OK_CONFLICT) {
     set_ipp_error (answer ?
-		   answer->request.status.status_code :
+		   ippGetStatusCode (answer) :
 		   cupsLastError ());
     if (answer)
       ippDelete (answer);
@@ -2467,7 +2473,7 @@ Connection_setPrinterLocation (Connection *self, PyObject *args)
       return NULL;
     }
 
-    if (answer && answer->request.status.status_code == IPP_NOT_POSSIBLE) {
+    if (answer && ippGetStatusCode (answer) == IPP_NOT_POSSIBLE) {
       // Perhaps it's a class, not a printer.
       ippDelete (answer);
       request = add_modify_class_request (name);
@@ -2476,9 +2482,9 @@ Connection_setPrinterLocation (Connection *self, PyObject *args)
 
   free (name);
   free (location);
-  if (!answer || answer->request.status.status_code > IPP_OK_CONFLICT) {
+  if (!answer || ippGetStatusCode (answer) > IPP_OK_CONFLICT) {
     set_ipp_error (answer ?
-		   answer->request.status.status_code :
+		   ippGetStatusCode (answer) :
 		   cupsLastError ());
     if (answer)
       ippDelete (answer);
@@ -2516,7 +2522,7 @@ Connection_setPrinterShared (Connection *self, PyObject *args)
       return NULL;
     }
 
-    if (answer && answer->request.status.status_code == IPP_NOT_POSSIBLE) {
+    if (answer && ippGetStatusCode (answer) == IPP_NOT_POSSIBLE) {
       // Perhaps it's a class, not a printer.
       ippDelete (answer);
       request = add_modify_class_request (name);
@@ -2524,9 +2530,9 @@ Connection_setPrinterShared (Connection *self, PyObject *args)
   }
 
   free (name);
-  if (!answer || answer->request.status.status_code > IPP_OK_CONFLICT) {
+  if (!answer || ippGetStatusCode (answer) > IPP_OK_CONFLICT) {
     set_ipp_error (answer ?
-		   answer->request.status.status_code :
+		   ippGetStatusCode (answer) :
 		   cupsLastError ());
     if (answer)
       ippDelete (answer);
@@ -2571,8 +2577,8 @@ Connection_setPrinterJobSheets (Connection *self, PyObject *args)
   for (i = 0; i < 2; i++) {
     a = ippAddStrings (request, IPP_TAG_PRINTER, IPP_TAG_NAME,
 		       "job-sheets-default", 2, NULL, NULL);
-    a->values[0].string.text = strdup (start);
-    a->values[1].string.text = strdup (end);
+    ippSetString(request, &a, 0, strdup (start));
+    ippSetString(request, &a, 1, strdup (end));
     Connection_begin_allow_threads (self);
     answer = cupsDoRequest (self->http, request, "/admin/");
     Connection_end_allow_threads (self);
@@ -2582,7 +2588,7 @@ Connection_setPrinterJobSheets (Connection *self, PyObject *args)
       return NULL;
     }
 
-    if (answer && answer->request.status.status_code == IPP_NOT_POSSIBLE) {
+    if (answer && ippGetStatusCode (answer) == IPP_NOT_POSSIBLE) {
       ippDelete (answer);
       // Perhaps it's a class, not a printer.
       request = add_modify_class_request (name);
@@ -2592,9 +2598,9 @@ Connection_setPrinterJobSheets (Connection *self, PyObject *args)
   free (name);
   free (start);
   free (end);
-  if (!answer || answer->request.status.status_code > IPP_OK_CONFLICT) {
+  if (!answer || ippGetStatusCode (answer) > IPP_OK_CONFLICT) {
     set_ipp_error (answer ?
-		   answer->request.status.status_code :
+		   ippGetStatusCode (answer) :
 		   cupsLastError ());
     if (answer)
       ippDelete (answer);
@@ -2639,7 +2645,7 @@ Connection_setPrinterErrorPolicy (Connection *self, PyObject *args)
       return NULL;
     }
 
-    if (answer && answer->request.status.status_code == IPP_NOT_POSSIBLE) {
+    if (answer && ippGetStatusCode (answer) == IPP_NOT_POSSIBLE) {
       ippDelete (answer);
       // Perhaps it's a class, not a printer.
       request = add_modify_class_request (name);
@@ -2648,9 +2654,9 @@ Connection_setPrinterErrorPolicy (Connection *self, PyObject *args)
 
   free (name);
   free (policy);
-  if (!answer || answer->request.status.status_code > IPP_OK_CONFLICT) {
+  if (!answer || ippGetStatusCode (answer) > IPP_OK_CONFLICT) {
     set_ipp_error (answer ?
-		   answer->request.status.status_code :
+		   ippGetStatusCode (answer) :
 		   cupsLastError ());
     if (answer)
       ippDelete (answer);
@@ -2695,7 +2701,7 @@ Connection_setPrinterOpPolicy (Connection *self, PyObject *args)
       return NULL;
     }
 
-    if (answer && answer->request.status.status_code == IPP_NOT_POSSIBLE) {
+    if (answer && ippGetStatusCode (answer) == IPP_NOT_POSSIBLE) {
       ippDelete (answer);
       // Perhaps it's a class, not a printer.
       request = add_modify_class_request (name);
@@ -2704,9 +2710,9 @@ Connection_setPrinterOpPolicy (Connection *self, PyObject *args)
 
   free (name);
   free (policy);
-  if (!answer || answer->request.status.status_code > IPP_OK_CONFLICT) {
+  if (!answer || ippGetStatusCode (answer) > IPP_OK_CONFLICT) {
     set_ipp_error (answer ?
-		   answer->request.status.status_code :
+		   ippGetStatusCode (answer) :
 		   cupsLastError ());
     if (answer)
       ippDelete (answer);
@@ -2750,21 +2756,21 @@ do_requesting_user_names (Connection *self, PyObject *args,
 	  int k;
 	  PyErr_SetString (PyExc_TypeError, "String required");
 	  for (k = 0; k < j; k++) {
-	    free (attr->values[k].string.text);
-	    attr->values[k].string.text = NULL;
+	    free ((void *)ippGetString (attr, k, NULL));
+	    ippSetString(request, &attr, k, NULL);
 	  }
 	  ippDelete (request);
 	  return NULL;
 	}
-	attr->values[j].string.text = strdup (PyString_AsString (username));
+	ippSetString(request, &attr, j, strdup (PyString_AsString (username)));
       }
     } else {
       attr = ippAddStrings (request, IPP_TAG_PRINTER, IPP_TAG_NAME,
 			    requeststr, 1, NULL, NULL);
       if (strstr (requeststr, "denied"))
-	attr->values[0].string.text = strdup ("none");
+	ippSetString(request, &attr, 0, strdup ("none"));
       else
-	attr->values[0].string.text = strdup ("all");
+	ippSetString(request, &attr, 0, strdup ("all"));
     }
     Connection_begin_allow_threads (self);
     answer = cupsDoRequest (self->http, request, "/admin/");
@@ -2775,7 +2781,7 @@ do_requesting_user_names (Connection *self, PyObject *args,
       return NULL;
     }
 
-    if (answer && answer->request.status.status_code == IPP_NOT_POSSIBLE) {
+    if (answer && ippGetStatusCode (answer) == IPP_NOT_POSSIBLE) {
       ippDelete (answer);
       // Perhaps it's a class, not a printer.
       request = add_modify_class_request (name);
@@ -2783,9 +2789,9 @@ do_requesting_user_names (Connection *self, PyObject *args,
   }
 
   free (name);
-  if (!answer || answer->request.status.status_code > IPP_OK_CONFLICT) {
+  if (!answer || ippGetStatusCode (answer) > IPP_OK_CONFLICT) {
     set_ipp_error (answer ?
-		   answer->request.status.status_code :
+		   ippGetStatusCode (answer) :
 		   cupsLastError ());
     if (answer)
       ippDelete (answer);
@@ -2872,7 +2878,7 @@ Connection_addPrinterOptionDefault (Connection *self, PyObject *args)
 			    opt, len, NULL, NULL);
       for (j = 0; j < len; j++) {
 	PyObject *each = PySequence_GetItem (pyvalue, j);
-	attr->values[j].string.text = PyObject_to_string (each);
+	ippSetString(request, &attr, j, PyObject_to_string (each));
       }
     } else
       ippAddString (request, IPP_TAG_PRINTER, IPP_TAG_NAME,
@@ -2887,7 +2893,7 @@ Connection_addPrinterOptionDefault (Connection *self, PyObject *args)
       return NULL;
     }
 
-    if (answer && answer->request.status.status_code == IPP_NOT_POSSIBLE) {
+    if (answer && ippGetStatusCode (answer) == IPP_NOT_POSSIBLE) {
       ippDelete (answer);
       // Perhaps it's a class, not a printer.
       request = add_modify_class_request (name);
@@ -2896,9 +2902,9 @@ Connection_addPrinterOptionDefault (Connection *self, PyObject *args)
 
   free (name);
   free (option);
-  if (!answer || answer->request.status.status_code > IPP_OK_CONFLICT) {
+  if (!answer || ippGetStatusCode (answer) > IPP_OK_CONFLICT) {
     set_ipp_error (answer ?
-		   answer->request.status.status_code :
+		   ippGetStatusCode (answer) :
 		   cupsLastError ());
     if (answer)
       ippDelete (answer);
@@ -2950,7 +2956,7 @@ Connection_deletePrinterOptionDefault (Connection *self, PyObject *args)
       return NULL;
     }
 
-    if (answer && answer->request.status.status_code == IPP_NOT_POSSIBLE) {
+    if (answer && ippGetStatusCode (answer) == IPP_NOT_POSSIBLE) {
       ippDelete (answer);
       // Perhaps it's a class, not a printer.
       request = add_modify_class_request (name);
@@ -2959,9 +2965,9 @@ Connection_deletePrinterOptionDefault (Connection *self, PyObject *args)
 
   free (name);
   free (option);
-  if (!answer || answer->request.status.status_code > IPP_OK_CONFLICT) {
+  if (!answer || ippGetStatusCode (answer) > IPP_OK_CONFLICT) {
     set_ipp_error (answer ?
-		   answer->request.status.status_code :
+		   ippGetStatusCode (answer) :
 		   cupsLastError ());
     if (answer)
       ippDelete (answer);
@@ -3048,7 +3054,7 @@ Connection_getPrinterAttributes (Connection *self, PyObject *args,
     Connection_begin_allow_threads (self);
     answer = cupsDoRequest (self->http, request, "/");
     Connection_end_allow_threads (self);
-    if (answer && answer->request.status.status_code == IPP_NOT_POSSIBLE) {
+    if (answer && ippGetStatusCode (answer) == IPP_NOT_POSSIBLE) {
       ippDelete (answer);
       if (uriobj)
 	break;
@@ -3067,9 +3073,9 @@ Connection_getPrinterAttributes (Connection *self, PyObject *args,
   if (requested_attrs)
     free_requested_attrs (n_attrs, attrs);
 
-  if (!answer || answer->request.status.status_code > IPP_OK_CONFLICT) {
+  if (!answer || ippGetStatusCode (answer) > IPP_OK_CONFLICT) {
     set_ipp_error (answer ?
-		   answer->request.status.status_code :
+		   ippGetStatusCode (answer) :
 		   cupsLastError ());
     if (answer)
       ippDelete (answer);
@@ -3079,28 +3085,28 @@ Connection_getPrinterAttributes (Connection *self, PyObject *args,
   }
 
   ret = PyDict_New ();
-  for (attr = answer->attrs; attr; attr = attr->next) {
-    while (attr && attr->group_tag != IPP_TAG_PRINTER)
-      attr = attr->next;
+  for (attr = ippFirstAttribute (answer); attr; attr = ippNextAttribute (answer)) {
+    while (attr && ippGetGroupTag (attr) != IPP_TAG_PRINTER)
+      attr = ippNextAttribute (answer);
 
     if (!attr)
       break;
 
-    for (; attr && attr->group_tag == IPP_TAG_PRINTER;
-	 attr = attr->next) {
-      size_t namelen = strlen (attr->name);
-      int is_list = attr->num_values > 1;
+    for (; attr && ippGetGroupTag (attr) == IPP_TAG_PRINTER;
+	 attr = ippNextAttribute (answer)) {
+      size_t namelen = strlen (ippGetName (attr));
+      int is_list = ippGetCount (attr) > 1;
 
-      debugprintf ("Attribute: %s\n", attr->name);
+      debugprintf ("Attribute: %s\n", ippGetName (attr));
       // job-sheets-default is special, since it is always two values.
       // Make it a tuple.
-      if (!strcmp (attr->name, "job-sheets-default") &&
-	  attr->value_tag == IPP_TAG_NAME) {
+      if (!strcmp (ippGetName (attr), "job-sheets-default") &&
+	  ippGetValueTag (attr) == IPP_TAG_NAME) {
 	PyObject *startobj, *endobj, *tuple;
 	const char *start, *end;
-	start = attr->values[0].string.text;
-	if (attr->num_values >= 2)
-	  end = attr->values[1].string.text;
+	start = ippGetString (attr, 0, NULL);
+	if (ippGetCount (attr) >= 2)
+	  end = ippGetString (attr, 1, NULL);
 	else
 	  end = "";
 
@@ -3134,7 +3140,7 @@ Connection_getPrinterAttributes (Connection *self, PyObject *args,
 	    NULL
 	  };
 
-	switch (attr->value_tag) {
+	switch (ippGetValueTag (attr)) {
 	case IPP_TAG_NAME:
 	case IPP_TAG_TEXT:
 	case IPP_TAG_KEYWORD:
@@ -3145,12 +3151,12 @@ Connection_getPrinterAttributes (Connection *self, PyObject *args,
 	case IPP_TAG_ENUM:
 	case IPP_TAG_INTEGER:
 	case IPP_TAG_RESOLUTION:
-	  is_list = !strcmp (attr->name + namelen - 10, "-supported");
+	  is_list = !strcmp (ippGetName (attr) + namelen - 10, "-supported");
 
 	  if (!is_list) {
 	    const char **opt;
 	    for (opt = multivalue_options; !is_list && *opt; opt++)
-	      is_list = !strcmp (attr->name, *opt);
+	      is_list = !strcmp (ippGetName (attr), *opt);
 	  }
 
 	default:
@@ -3160,11 +3166,11 @@ Connection_getPrinterAttributes (Connection *self, PyObject *args,
 
       if (is_list) {
 	PyObject *list = PyList_from_attr_values (attr);
-	PyDict_SetItemString (ret, attr->name, list);
+	PyDict_SetItemString (ret, ippGetName (attr), list);
 	Py_DECREF (list);
       } else {
 	PyObject *val = PyObject_from_attr_value (attr, i);
-	PyDict_SetItemString (ret, attr->name, val);
+	PyDict_SetItemString (ret, ippGetName (attr), val);
       }
     }
 
@@ -3213,8 +3219,8 @@ Connection_addPrinterToClass (Connection *self, PyObject *args)
     printers = ippFindAttribute (answer, "member-names", IPP_TAG_NAME);
     if (printers) {
       int i;
-      for (i = 0; i < printers->num_values; i++) {
-	if (!strcasecmp (printers->values[i].string.text, printername)) {
+      for (i = 0; i < ippGetCount (printers); i++) {
+	if (!strcasecmp (ippGetString (printers, i, NULL), printername)) {
 	  ippDelete (answer);
 	  PyErr_SetString (PyExc_RuntimeError, "Printer already in class");
 	  free (printername);
@@ -3237,11 +3243,13 @@ Connection_addPrinterToClass (Connection *self, PyObject *args)
       ipp_attribute_t *attr;
       int i;
       attr = ippAddStrings (request, IPP_TAG_PRINTER, IPP_TAG_URI,
-			    "member-uris", printers->num_values + 1,
+			    "member-uris", ippGetCount (printers) + 1,
 			    NULL, NULL);
-      for (i = 0; i < printers->num_values; i++)
-	attr->values[i].string.text = strdup (printers->values[i].string.text);
-      attr->values[printers->num_values].string.text = strdup (printeruri);
+      for (i = 0; i < ippGetCount (printers); i++)
+        ippSetString(request, &attr, i,
+                     strdup (ippGetString (printers, i, NULL)));
+      ippSetString(request, &attr, ippGetCount (printers), strdup (printeruri));
+
     }
 
     ippDelete (answer);
@@ -3261,9 +3269,9 @@ Connection_addPrinterToClass (Connection *self, PyObject *args)
     return NULL;
   }
 
-  if (!answer || answer->request.status.status_code > IPP_OK_CONFLICT) {
+  if (!answer || ippGetStatusCode (answer) > IPP_OK_CONFLICT) {
     set_ipp_error (answer ?
-		   answer->request.status.status_code :
+		   ippGetStatusCode (answer) :
 		   cupsLastError ());
     if (answer)
       ippDelete (answer);
@@ -3322,19 +3330,19 @@ Connection_deletePrinterFromClass (Connection *self, PyObject *args)
   }
 
   printers = ippFindAttribute (answer, "member-names", IPP_TAG_NAME);
-  for (i = 0; printers && i < printers->num_values; i++)
-    if (!strcasecmp (printers->values[i].string.text, printername))
+  for (i = 0; printers && i < ippGetCount (printers); i++)
+    if (!strcasecmp (ippGetString (printers, i, NULL), printername))
       break;
 
   free (printername);
-  if (!printers || i == printers->num_values) {
+  if (!printers || i == ippGetCount (printers)) {
     ippDelete (answer);
     PyErr_SetString (PyExc_RuntimeError, "Printer not in class");
     return NULL;
   }
 
   printers = ippFindAttribute (answer, "member-uris", IPP_TAG_URI);
-  if (!printers || i >= printers->num_values) {
+  if (!printers || i >= ippGetCount (printers)) {
     ippDelete (answer);
     PyErr_SetString (PyExc_RuntimeError, "No member URIs returned");
     return NULL;
@@ -3345,21 +3353,21 @@ Connection_deletePrinterFromClass (Connection *self, PyObject *args)
 		"printer-uri", NULL, classuri);
 
   // Only printer in class?  Delete the class.
-  if (printers->num_values == 1)
-    request->request.op.operation_id = CUPS_DELETE_CLASS;
+  if (ippGetCount (printers) == 1)
+    ippSetOperation (request, CUPS_DELETE_CLASS);
   else {
     // Trim the printer from the list.
     ipp_attribute_t *newlist;
     int j;
     newlist = ippAddStrings (request, IPP_TAG_PRINTER, IPP_TAG_URI,
-			     "member-uris", printers->num_values - 1,
+			     "member-uris", ippGetCount (printers) - 1,
 			     NULL, NULL);
     for (j = 0; j < i; j++)
-      newlist->values[j].string.text =
-	strdup (printers->values[j].string.text);
-    for (j = i; j < newlist->num_values; j++)
-      newlist->values[j].string.text =
-	strdup (printers->values[j + 1].string.text);
+      ippSetString(request, &newlist, j,
+                   strdup (ippGetString (printers, j, NULL)));
+    for (j = i; j < ippGetCount(newlist); j++)
+      ippSetString(request, &newlist, j,
+                   strdup (ippGetString (printers, j+1, NULL)));
   }
 
   ippDelete (answer);
@@ -3372,9 +3380,9 @@ Connection_deletePrinterFromClass (Connection *self, PyObject *args)
     return NULL;
   }
 
-  if (!answer || answer->request.status.status_code > IPP_OK_CONFLICT) {
+  if (!answer || ippGetStatusCode (answer) > IPP_OK_CONFLICT) {
     set_ipp_error (answer ?
-		   answer->request.status.status_code :
+		   ippGetStatusCode (answer) :
 		   cupsLastError ());
     if (answer)
       ippDelete (answer);
@@ -3408,9 +3416,9 @@ Connection_deleteClass (Connection *self, PyObject *args)
   Connection_begin_allow_threads (self);
   answer = cupsDoRequest (self->http, request, "/admin/");
   Connection_end_allow_threads (self);
-  if (!answer || answer->request.status.status_code > IPP_OK_CONFLICT) {
+  if (!answer || ippGetStatusCode (answer) > IPP_OK_CONFLICT) {
     set_ipp_error (answer ?
-		   answer->request.status.status_code :
+		   ippGetStatusCode (answer) :
 		   cupsLastError ());
     if (answer)
       ippDelete (answer);
@@ -3698,7 +3706,7 @@ Connection_printTestPage (Connection *self, PyObject *args, PyObject *kwds)
     Connection_begin_allow_threads (self);
     answer = cupsDoFileRequest (self->http, request, resource, file);
     Connection_end_allow_threads (self);
-    if (answer && answer->request.status.status_code == IPP_NOT_POSSIBLE) {
+    if (answer && ippGetStatusCode (answer) == IPP_NOT_POSSIBLE) {
       ippDelete (answer);
       // Perhaps it's a class, not a printer.
       snprintf (uri, sizeof (uri), "ipp://localhost/classes/%s", printer);
@@ -3715,9 +3723,9 @@ Connection_printTestPage (Connection *self, PyObject *args, PyObject *kwds)
   if (userobj)
     free (user);
 
-  if (!answer || answer->request.status.status_code > IPP_OK_CONFLICT) {
+  if (!answer || ippGetStatusCode (answer) > IPP_OK_CONFLICT) {
     set_ipp_error (answer ?
-		   answer->request.status.status_code :
+		   ippGetStatusCode (answer) :
 		   cupsLastError ());
     if (answer)
       ippDelete (answer);
@@ -3726,7 +3734,7 @@ Connection_printTestPage (Connection *self, PyObject *args, PyObject *kwds)
 
   attr = ippFindAttribute (answer, "job-id", IPP_TAG_INTEGER);
   if (attr)
-    jobid = attr->values[0].integer;
+    jobid = ippGetInteger (attr, 0);
 
   ippDelete (answer);
   return Py_BuildValue ("i", jobid);
@@ -3922,8 +3930,8 @@ Connection_getSubscriptions (Connection *self, PyObject *args, PyObject *kwds)
   Connection_begin_allow_threads (self);
   answer = cupsDoRequest (self->http, request, "/");
   Connection_end_allow_threads (self);
-  if (!answer || answer->request.status.status_code > IPP_OK_CONFLICT) {
-    set_ipp_error (answer ? answer->request.status.status_code :
+  if (!answer || ippGetStatusCode (answer) > IPP_OK_CONFLICT) {
+    set_ipp_error (answer ? ippGetStatusCode (answer) :
 		   cupsLastError ());
     if (answer)
       ippDelete (answer);
@@ -3932,14 +3940,14 @@ Connection_getSubscriptions (Connection *self, PyObject *args, PyObject *kwds)
   }
 
   result = PyList_New (0);
-  for (attr = answer->attrs; attr; attr = attr->next)
-    if (attr->group_tag == IPP_TAG_SUBSCRIPTION)
+  for (attr = ippFirstAttribute (answer); attr; attr = ippNextAttribute (answer))
+    if (ippGetGroupTag (attr) == IPP_TAG_SUBSCRIPTION)
       break;
 
   subscription = NULL;
-  for (; attr; attr = attr->next) {
+  for (; attr; attr = ippNextAttribute (answer)) {
     PyObject *obj;
-    if (attr->group_tag == IPP_TAG_ZERO) {
+    if (ippGetGroupTag (attr) == IPP_TAG_ZERO) {
       // End of subscription.
       if (subscription) {
 	PyList_Append (result, subscription);
@@ -3950,7 +3958,7 @@ Connection_getSubscriptions (Connection *self, PyObject *args, PyObject *kwds)
       continue;
     }
 
-    if (attr->num_values > 1 || !strcmp (attr->name, "notify-events"))
+    if (ippGetCount (attr) > 1 || !strcmp (ippGetName (attr), "notify-events"))
       obj = PyList_from_attr_values (attr);
     else
       obj = PyObject_from_attr_value (attr, 0);
@@ -3962,7 +3970,7 @@ Connection_getSubscriptions (Connection *self, PyObject *args, PyObject *kwds)
     if (!subscription)
       subscription = PyDict_New ();
 
-    PyDict_SetItemString (subscription, attr->name, obj);
+    PyDict_SetItemString (subscription, ippGetName (attr), obj);
     Py_DECREF (obj);
   }
 
@@ -4060,7 +4068,8 @@ Connection_createSubscription (Connection *self, PyObject *args,
 			  n, NULL, NULL);
     for (i = 0; i < n; i++) {
       PyObject *event = PyList_GetItem (events, i);
-      attr->values[i].string.text = strdup (PyString_AsString (event));
+      //attr->values[i].string.text = strdup (PyString_AsString (event));
+      ippSetString(request, &attr, i, strdup (PyString_AsString (event)));
     }
   }
 
@@ -4079,8 +4088,8 @@ Connection_createSubscription (Connection *self, PyObject *args,
   Connection_begin_allow_threads (self);
   answer = cupsDoRequest (self->http, request, "/");
   Connection_end_allow_threads (self);
-  if (!answer || answer->request.status.status_code > IPP_OK_CONFLICT) {
-    set_ipp_error (answer ? answer->request.status.status_code :
+  if (!answer || ippGetStatusCode (answer) > IPP_OK_CONFLICT) {
+    set_ipp_error (answer ? ippGetStatusCode (answer) :
 		   cupsLastError ());
     if (answer)
       ippDelete (answer);
@@ -4089,14 +4098,14 @@ Connection_createSubscription (Connection *self, PyObject *args,
   }
 
   i = -1;
-  for (attr = answer->attrs; attr; attr = attr->next) {
-    if (attr->group_tag == IPP_TAG_SUBSCRIPTION) {
-      if (attr->value_tag == IPP_TAG_INTEGER &&
-	  !strcmp (attr->name, "notify-subscription-id"))
-	i = attr->values[0].integer;
-      else if (attr->value_tag == IPP_TAG_ENUM &&
-	       !strcmp (attr->name, "notify-status-code"))
-	debugprintf ("notify-status-code = %d\n", attr->values[0].integer);
+  for (attr = ippFirstAttribute (answer); attr; attr = ippNextAttribute (answer)) {
+    if (ippGetGroupTag (attr) == IPP_TAG_SUBSCRIPTION) {
+      if (ippGetValueTag (attr) == IPP_TAG_INTEGER &&
+	  !strcmp (ippGetName (attr), "notify-subscription-id"))
+	i = ippGetInteger (attr, 0);
+      else if (ippGetValueTag (attr) == IPP_TAG_ENUM &&
+	       !strcmp (ippGetName (attr), "notify-status-code"))
+	debugprintf ("notify-status-code = %d\n", ippGetInteger (attr, 0));
     }
   }
 
@@ -4162,7 +4171,8 @@ Connection_getNotifications (Connection *self, PyObject *args, PyObject *kwds)
 			 "notify-subscription-ids", num_ids, NULL);
   for (i = 0; i < num_ids; i++) {
     PyObject *id = PyList_GetItem (subscription_ids, i);
-    attr->values[i].integer = PyInt_AsLong (id);
+    //attr->values[i].integer = PyInt_AsLong (id);
+    ippSetInteger (request, &attr, i, PyInt_AsLong (id));
   }
 
   if (sequence_numbers) {
@@ -4170,15 +4180,16 @@ Connection_getNotifications (Connection *self, PyObject *args, PyObject *kwds)
 			   "notify-sequence-numbers", num_seqs, NULL);
     for (i = 0; i < num_seqs; i++) {
       PyObject *num = PyList_GetItem (sequence_numbers, i);
-      attr->values[i].integer = PyInt_AsLong (num);
+      //attr->values[i].integer = PyInt_AsLong (num);
+      ippSetInteger (request, &attr, i, PyInt_AsLong (num));
     }
   }
   
   Connection_begin_allow_threads (self);
   answer = cupsDoRequest (self->http, request, "/");
   Connection_end_allow_threads (self);
-  if (!answer || answer->request.status.status_code > IPP_OK_CONFLICT) {
-    set_ipp_error (answer ? answer->request.status.status_code :
+  if (!answer || ippGetStatusCode (answer) > IPP_OK_CONFLICT) {
+    set_ipp_error (answer ? ippGetStatusCode (answer) :
 		   cupsLastError ());
     if (answer)
       ippDelete (answer);
@@ -4191,27 +4202,27 @@ Connection_getNotifications (Connection *self, PyObject *args, PyObject *kwds)
   // Result-wide attributes.
   attr = ippFindAttribute (answer, "notify-get-interval", IPP_TAG_INTEGER);
   if (attr) {
-    PyObject *val = PyInt_FromLong (attr->values[0].integer);
-    PyDict_SetItemString (result, attr->name, val);
+    PyObject *val = PyInt_FromLong (ippGetInteger (attr, 0));
+    PyDict_SetItemString (result, ippGetName (attr), val);
     Py_DECREF (val);
   }
 
   attr = ippFindAttribute (answer, "printer-up-time", IPP_TAG_INTEGER);
   if (attr) {
-    PyObject *val = PyInt_FromLong (attr->values[0].integer);
-    PyDict_SetItemString (result, attr->name, val);
+    PyObject *val = PyInt_FromLong (ippGetInteger (attr, 0));
+    PyDict_SetItemString (result, ippGetName (attr), val);
     Py_DECREF (val);
   }
 
   events = PyList_New (0);
-  for (attr = answer->attrs; attr; attr = attr->next)
-    if (attr->group_tag == IPP_TAG_EVENT_NOTIFICATION)
+  for (attr = ippFirstAttribute (answer); attr; attr = ippNextAttribute (answer))
+    if (ippGetGroupTag (attr) == IPP_TAG_EVENT_NOTIFICATION)
       break;
 
   event = NULL;
-  for (; attr; attr = attr->next) {
+  for (; attr; attr = ippNextAttribute (answer)) {
     PyObject *obj;
-    if (attr->group_tag == IPP_TAG_ZERO) {
+    if (ippGetGroupTag (attr) == IPP_TAG_ZERO) {
       // End of event notification.
       if (event) {
 	PyList_Append (events, event);
@@ -4222,10 +4233,10 @@ Connection_getNotifications (Connection *self, PyObject *args, PyObject *kwds)
       continue;
     }
 
-    if (attr->num_values > 1 ||
-	!strcmp (attr->name, "notify-events") ||
-	!strcmp (attr->name, "printer-state-reasons") ||
-	!strcmp (attr->name, "job-printer-state-reasons"))
+    if (ippGetCount (attr) > 1 ||
+	!strcmp (ippGetName (attr), "notify-events") ||
+	!strcmp (ippGetName (attr), "printer-state-reasons") ||
+	!strcmp (ippGetName (attr), "job-printer-state-reasons"))
       obj = PyList_from_attr_values (attr);
     else
       obj = PyObject_from_attr_value (attr, 0);
@@ -4237,7 +4248,7 @@ Connection_getNotifications (Connection *self, PyObject *args, PyObject *kwds)
     if (!event)
       event = PyDict_New ();
 
-    PyDict_SetItemString (event, attr->name, obj);
+    PyDict_SetItemString (event, ippGetName (attr), obj);
     Py_DECREF (obj);
   }
 
@@ -4281,8 +4292,8 @@ Connection_renewSubscription (Connection *self, PyObject *args, PyObject *kwds)
   Connection_begin_allow_threads (self);
   answer = cupsDoRequest (self->http, request, "/");
   Connection_end_allow_threads (self);
-  if (!answer || answer->request.status.status_code > IPP_OK_CONFLICT) {
-    set_ipp_error (answer ? answer->request.status.status_code :
+  if (!answer || ippGetStatusCode (answer) > IPP_OK_CONFLICT) {
+    set_ipp_error (answer ? ippGetStatusCode (answer) :
 		   cupsLastError ());
     if (answer)
       ippDelete (answer);
@@ -4316,8 +4327,8 @@ Connection_cancelSubscription (Connection *self, PyObject *args)
   Connection_begin_allow_threads (self);
   answer = cupsDoRequest (self->http, request, "/");
   Connection_end_allow_threads (self);
-  if (!answer || answer->request.status.status_code > IPP_OK_CONFLICT) {
-    set_ipp_error (answer ? answer->request.status.status_code :
+  if (!answer || ippGetStatusCode (answer) > IPP_OK_CONFLICT) {
+    set_ipp_error (answer ? ippGetStatusCode (answer) :
 		   cupsLastError ());
     if (answer)
       ippDelete (answer);
diff --git a/cupsconnection.h b/cupsconnection.h
index d1ef17d..04909e4 100644
--- a/cupsconnection.h
+++ b/cupsconnection.h
@@ -14,7 +14,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
 #ifndef HAVE_CUPSCONNECTION_H
diff --git a/cupsipp.c b/cupsipp.c
index 1d309db..ac34004 100644
--- a/cupsipp.c
+++ b/cupsipp.c
@@ -15,7 +15,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
 #include "cupsipp.h"
@@ -370,18 +370,18 @@ IPPRequest_getAttributes (IPPRequest *self, void *closure)
 {
   PyObject *attrs = PyList_New (0);
   ipp_attribute_t *attr;
-  for (attr = self->ipp->attrs; attr; attr = attr->next)
+  for (attr = ippFirstAttribute (self->ipp); attr; attr = ippNextAttribute(self->ipp))
     {
       PyObject *largs = NULL;
       PyObject *lkwlist = NULL;
       PyObject *values = NULL;
       IPPAttribute *attribute = NULL;
 
-      debugprintf ("%s: ", attr->name);
-      if (attr->value_tag == IPP_TAG_ZERO ||
-	  attr->value_tag == IPP_TAG_NOVALUE ||
-	  attr->value_tag == IPP_TAG_NOTSETTABLE ||
-	  attr->value_tag == IPP_TAG_ADMINDEFINE) {
+      debugprintf ("%s: ", ippGetName (attr));
+      if (ippGetValueTag (attr) == IPP_TAG_ZERO ||
+	  ippGetValueTag (attr) == IPP_TAG_NOVALUE ||
+	  ippGetValueTag (attr) == IPP_TAG_NOTSETTABLE ||
+	  ippGetValueTag (attr) == IPP_TAG_ADMINDEFINE) {
 	debugprintf ("no value\n");
       } else {
 	PyObject *value = NULL;
@@ -392,25 +392,25 @@ IPPRequest_getAttributes (IPPRequest *self, void *closure)
 	if (!values)
 	  goto fail_add;
 
-	for (i = 0; i < attr->num_values; i++) {
-	  switch (attr->value_tag) {
+	for (i = 0; i < ippGetCount (attr); i++) {
+	  switch (ippGetValueTag (attr)) {
 	  case IPP_TAG_INTEGER:
 	  case IPP_TAG_ENUM:
 	  case IPP_TAG_RANGE:
-	    value = PyInt_FromLong (attr->values[i].integer);
-	    debugprintf ("i%d", attr->values[i].integer);
+	    value = PyInt_FromLong (ippGetInteger (attr, i));
+	    debugprintf ("i%d", ippGetInteger (attr, i));
 	    break;
 
 	  case IPP_TAG_BOOLEAN:
-	    value = PyBool_FromLong (attr->values[i].boolean);
-	    debugprintf ("b%d", attr->values[i].integer);
+	    value = PyBool_FromLong (ippGetBoolean (attr, i));
+	    debugprintf ("b%d", ippGetInteger (attr, i));
 	    break;
 
 	  case IPP_TAG_TEXT:
-	    value = PyUnicode_Decode (attr->values[i].string.text,
-				      strlen (attr->values[i].string.text),
+	    value = PyUnicode_Decode (ippGetString (attr, i, NULL),
+				      strlen (ippGetString (attr, i, NULL)),
 				      "utf-8", NULL);
-	    debugprintf ("u%s", attr->values[i].string.text);
+	    debugprintf ("u%s", ippGetString (attr, i, NULL));
 	    break;
 
 	  case IPP_TAG_NAME:
@@ -419,14 +419,14 @@ IPPRequest_getAttributes (IPPRequest *self, void *closure)
 	  case IPP_TAG_MIMETYPE:
 	  case IPP_TAG_CHARSET:
 	  case IPP_TAG_LANGUAGE:
-	    value = PyString_FromString (attr->values[i].string.text);
-	    debugprintf ("s%s", attr->values[i].string.text);
+	    value = PyString_FromString (ippGetString (attr, i, NULL));
+	    debugprintf ("s%s", ippGetString (attr, i, NULL));
 	    break;
 
 	  default:
 	    value = NULL;
 	    unknown_value_tag = 1;
-	    debugprintf ("Unable to encode value tag %d\n", attr->value_tag);
+	    debugprintf ("Unable to encode value tag %d\n", ippGetValueTag (attr));
 	  }
 
 	  if (!value)
@@ -458,15 +458,15 @@ IPPRequest_getAttributes (IPPRequest *self, void *closure)
 
       if (values) {
 	largs = Py_BuildValue ("(iisO)",
-			       attr->group_tag,
-			       attr->value_tag,
-			       attr->name,
+			       ippGetGroupTag (attr),
+			       ippGetValueTag (attr),
+			       ippGetName (attr),
 			       values);
 	Py_DECREF (values);
 	values = NULL;
       } else
-	largs = Py_BuildValue ("(iis)", attr->group_tag, attr->value_tag,
-			       attr->name ? attr->name : "");
+	largs = Py_BuildValue ("(iis)", ippGetGroupTag (attr), ippGetValueTag (attr),
+			       ippGetName (attr) ? ippGetName (attr) : "");
 
       if (!largs)
 	goto fail_add;
diff --git a/cupsipp.h b/cupsipp.h
index 356feb7..8199ee2 100644
--- a/cupsipp.h
+++ b/cupsipp.h
@@ -15,7 +15,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
 #ifndef HAVE_CUPSIPP_H
diff --git a/cupsmodule.c b/cupsmodule.c
index eea59ae..1aba77d 100644
--- a/cupsmodule.c
+++ b/cupsmodule.c
@@ -1,6 +1,6 @@
 /*
  * cups - Python bindings for CUPS
- * Copyright (C) 2002, 2005, 2006, 2007, 2008, 2009, 2010, 2011  Red Hat, Inc
+ * Copyright (C) 2002, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012  Red Hat, Inc
  * Author: Tim Waugh <twaugh@redhat.com>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -15,7 +15,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
 #include <stdarg.h>
@@ -37,6 +37,25 @@
 static pthread_key_t tls_key = -1;
 static pthread_once_t tls_key_once = PTHREAD_ONCE_INIT;
 
+#if CUPS_VERSION_MAJOR > 1 || (CUPS_VERSION_MAJOR == 1 && CUPS_VERSION_MINOR >= 3)
+# define CUPS_PRINTER_DISCOVERED	0x1000000
+# define CUPS_SERVER_REMOTE_ANY		"_remote_any"
+#endif /* CUPS < 1.3 */
+
+#if CUPS_VERSION_MAJOR < 1 || (CUPS_VERSION_MAJOR == 1 && CUPS_VERSION_MINOR < 4)
+# define HTTP_AUTHORIZATION_CANCELED	1000
+#endif /* CUPS < 1.4 */
+
+#if CUPS_VERSION_MAJOR < 1 || (CUPS_VERSION_MAJOR == 1 && CUPS_VERSION_MINOR < 5)
+# define HTTP_PKI_ERROR			1001
+# define IPP_AUTHENTICATION_CANCELED	0x1000
+# define IPP_PKI_ERROR			0x1001
+#endif /* CUPS < 1.5 */
+
+#if (CUPS_VERSION_MAJOR == 1 && CUPS_VERSION_MINOR > 5)
+# define CUPS_SERVER_REMOTE_PRINTERS	"_remote_printers"
+#endif /* CUPS > 1.5 */
+
 //////////////////////
 // Worker functions //
 //////////////////////
@@ -188,6 +207,138 @@ do_password_callback (const char *prompt)
 }
 #endif /* !HAVE_CUPS_1_4 */
 
+#ifndef HAVE_CUPS_1_6
+int
+ippGetBoolean(ipp_attribute_t *attr,
+              int             element)
+{
+  return (attr->values[element].boolean);
+}
+
+int
+ippGetCount(ipp_attribute_t *attr)
+{
+  return (attr->num_values);
+}
+
+ipp_tag_t
+ippGetGroupTag(ipp_attribute_t *attr)
+{
+  return (attr->group_tag);
+}
+
+int
+ippGetInteger(ipp_attribute_t *attr,
+              int             element)
+{
+  return (attr->values[element].integer);
+}
+
+const char *
+ippGetName(ipp_attribute_t *attr)
+{
+  return (attr->name);
+}
+
+ipp_op_t
+ippGetOperation(ipp_t *ipp)
+{
+  return (ipp->request.op.operation_id);
+}
+
+int
+ippGetRange(ipp_attribute_t *attr,
+	    int             element,
+	    int             *uppervalue)
+{
+  if (uppervalue)
+    *uppervalue = attr->values[element].range.upper;
+
+  return (attr->values[element].range.lower);
+}
+
+int
+ippGetResolution(
+    ipp_attribute_t *attr,
+    int             element,
+    int             *yres,
+    ipp_res_t       *units)
+{
+  if (yres)
+    *yres = attr->values[element].resolution.yres;
+
+  if (units)
+    *units = attr->values[element].resolution.units;
+
+  return (attr->values[element].resolution.xres);
+}
+
+ipp_status_t
+ippGetStatusCode(ipp_t *ipp)
+{
+  return (ipp->request.status.status_code);
+}
+
+const char *
+ippGetString(ipp_attribute_t *attr,
+             int             element,
+             const char      **language)
+{
+  return (attr->values[element].string.text);
+}
+
+ipp_tag_t
+ippGetValueTag(ipp_attribute_t *attr)
+{
+  return (attr->value_tag);
+}
+
+ipp_attribute_t	*
+ippFirstAttribute(ipp_t *ipp)
+{
+  if (!ipp)
+    return (NULL);
+  return (ipp->current = ipp->attrs);
+}
+
+ipp_attribute_t *
+ippNextAttribute(ipp_t *ipp)
+{
+  if (!ipp || !ipp->current)
+    return (NULL);
+  return (ipp->current = ipp->current->next);
+}
+
+int
+ippSetInteger(ipp_t           *ipp,
+              ipp_attribute_t **attr,
+              int             element,
+              int             intvalue)
+{
+  (*attr)->values[element].integer = intvalue;
+  return (1);
+}
+
+int
+ippSetOperation(ipp_t    *ipp,
+                ipp_op_t op)
+{
+  ipp->request.op.operation_id = op;
+  return (1);
+}
+
+int
+ippSetString(ipp_t           *ipp,
+             ipp_attribute_t **attr,
+             int             element,
+             const char      *strvalue)
+{
+  (*attr)->values[element].string.text = (char *) strvalue;
+  return (1);
+}
+
+#endif
+
 //////////////////////////
 // Module-level methods //
 //////////////////////////
@@ -659,9 +810,7 @@ initcups (void)
   INT_CONSTANT (CUPS_PRINTER_AUTHENTICATED);
   INT_CONSTANT (CUPS_PRINTER_COMMANDS);
   INT_CONSTANT (CUPS_PRINTER_OPTIONS);
-#if CUPS_VERSION_MAJOR > 1 || (CUPS_VERSION_MAJOR == 1 && CUPS_VERSION_MINOR >= 3)
   INT_CONSTANT (CUPS_PRINTER_DISCOVERED);
-#endif /* CUPS 1.3 */
 
   // HTTP encryption
   INT_CONSTANT (HTTP_ENCRYPT_IF_REQUESTED);
@@ -685,12 +834,8 @@ initcups (void)
   INT_CONSTANT (HTTP_SERVICE_UNAVAILABLE);
   INT_CONSTANT (HTTP_GATEWAY_TIMEOUT);
   INT_CONSTANT (HTTP_NOT_SUPPORTED);
-#if CUPS_VERSION_MAJOR > 1 || (CUPS_VERSION_MAJOR == 1 && CUPS_VERSION_MINOR >= 4)
   INT_CONSTANT (HTTP_AUTHORIZATION_CANCELED);
-#endif /* CUPS 1.4 */
-#if CUPS_VERSION_MAJOR > 1 || (CUPS_VERSION_MAJOR == 1 && CUPS_VERSION_MINOR >= 5)
   INT_CONSTANT (HTTP_PKI_ERROR);
-#endif /* CUPS 1.5 */
 
   // PPD UI enum
   INT_CONSTANT (PPD_UI_BOOLEAN);
@@ -810,10 +955,8 @@ initcups (void)
   INT_CONSTANT (IPP_ERROR_JOB_CANCELLED);
   INT_CONSTANT (IPP_MULTIPLE_JOBS_NOT_SUPPORTED);
   INT_CONSTANT (IPP_PRINTER_IS_DEACTIVATED);
-#if CUPS_VERSION_MAJOR > 1 || (CUPS_VERSION_MAJOR == 1 && CUPS_VERSION_MINOR >= 5)
   INT_CONSTANT (IPP_AUTHENTICATION_CANCELED);
   INT_CONSTANT (IPP_PKI_ERROR);
-#endif /* CUPS 1.5 */
 
   // IPP states
   INT_CONSTANT (IPP_ERROR);
@@ -853,9 +996,7 @@ initcups (void)
   STR_CONSTANT (CUPS_SERVER_REMOTE_PRINTERS);
   STR_CONSTANT (CUPS_SERVER_SHARE_PRINTERS);
   STR_CONSTANT (CUPS_SERVER_USER_CANCEL_ANY);
-#if CUPS_VERSION_MAJOR > 1 || (CUPS_VERSION_MAJOR == 1 && CUPS_VERSION_MINOR >= 3)
   STR_CONSTANT (CUPS_SERVER_REMOTE_ANY);
-#endif /* CUPS 1.3 */
 
   // Exceptions
   obj = PyDict_New ();
diff --git a/cupsmodule.h b/cupsmodule.h
index 38095a6..c30d0e3 100644
--- a/cupsmodule.h
+++ b/cupsmodule.h
@@ -14,7 +14,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
 #ifndef HAVE_CUPSMODULE_H
@@ -49,6 +49,10 @@ extern void debugprintf (const char *fmt, ...) FORMAT ((__printf__, 1, 2));
 #define HAVE_CUPS_1_4 1
 #endif
 
+#if (CUPS_VERSION_MAJOR > 1) || (CUPS_VERSION_MINOR > 5)
+#define HAVE_CUPS_1_6 1
+#endif
+
 #ifndef HAVE_CUPS_1_2
 #error pycups requires CUPS 1.2.x
 #endif
@@ -65,4 +69,28 @@ struct TLS
 
 extern struct TLS *get_TLS (void);
 
+#ifndef HAVE_CUPS_1_6
+int ippGetBoolean(ipp_attribute_t *attr, int element);
+int ippGetCount(ipp_attribute_t *attr);
+ipp_tag_t ippGetGroupTag(ipp_attribute_t *attr);
+int ippGetInteger(ipp_attribute_t *attr, int element);
+const char * ippGetName(ipp_attribute_t *attr);
+ipp_op_t ippGetOperation(ipp_t *ipp);
+int ippGetRange(ipp_attribute_t *attr, int element, int *uppervalue);
+int ippGetResolution(ipp_attribute_t *attr, int element,
+                     int *yres, ipp_res_t *units);
+ipp_status_t ippGetStatusCode(ipp_t *ipp);
+const char * ippGetString(ipp_attribute_t *attr, int element,
+                          const char **language);
+ipp_tag_t ippGetValueTag(ipp_attribute_t *attr);
+ipp_attribute_t	* ippFirstAttribute(ipp_t *ipp);
+ipp_attribute_t * ippNextAttribute(ipp_t *ipp);
+int ippSetInteger(ipp_t *ipp, ipp_attribute_t **attr,
+                  int element, int intvalue);
+int ippSetOperation(ipp_t *ipp, ipp_op_t op);
+int ippSetString(ipp_t *ipp, ipp_attribute_t **attr,
+                 int element, const char *strvalue);
+#endif
+
+
 #endif /* HAVE_CUPSMODULE_H */
diff --git a/cupsppd.c b/cupsppd.c
index 57eecb1..0f9a821 100644
--- a/cupsppd.c
+++ b/cupsppd.c
@@ -14,7 +14,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
 #include "cupsppd.h"
@@ -236,10 +236,12 @@ PPD_init (PPD *self, PyObject *args, PyObject *kwds)
 static void
 PPD_dealloc (PPD *self)
 {
-  debugprintf ("- PPD %p (fd %d)\n", self, fileno (self->file));
-
-  if (self->file)
+  if (self->file) {
+    debugprintf ("- PPD %p (fd %d)\n", self, fileno (self->file));
     fclose (self->file);
+  } else
+    debugprintf ("- PPD %p (no fd)\n", self);
+
   if (self->ppd)
     ppdClose (self->ppd);
   if (self->conv_from)
diff --git a/cupsppd.h b/cupsppd.h
index 6ceed04..1866412 100644
--- a/cupsppd.h
+++ b/cupsppd.h
@@ -14,7 +14,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
 #ifndef HAVE_CUPSPPD_H
diff --git a/postscriptdriver.prov b/postscriptdriver.prov
index 9fcee98..7bf74b1 100755
--- a/postscriptdriver.prov
+++ b/postscriptdriver.prov
@@ -15,7 +15,7 @@
 
 ## You should have received a copy of the GNU General Public License
 ## along with this program; if not, write to the Free Software
-## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 import sys
 
diff --git a/setup.py b/setup.py
index f1fa38f..d2db098 100644
--- a/setup.py
+++ b/setup.py
@@ -15,7 +15,7 @@
 
 ## You should have received a copy of the GNU General Public License
 ## along with this program; if not, write to the Free Software
-## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 """This is a set of Python bindings for the libcups library from the
 CUPS project.
