Index: server/lib/ipprequest.py
===================================================================
--- server/lib/ipprequest.py	(revision 4ec7caa5478479c329bfc1eeff8ac44e24631060)
+++ server/lib/ipprequest.py	(revision d56a0bc5dc7dc8786c30fb5dfefec198f02e53df)
@@ -10,46 +10,59 @@
     
     # various tags
-    ZERO_NAME_LENGTH                  = 0X00
-    OPERATION_ATTRIBUTES_TAG          = 0X01
-    JOB_ATTRIBUTES_TAG                = 0X02
-    END_OF_ATTRIBUTES_TAG             = 0X03
-    PRINTER_ATTRIBUTES_TAG            = 0X04
-    UNSUPPORTED_ATTRIBUTES_TAG        = 0X05
+    ZERO_NAME_LENGTH                  = 0x00
+    OPERATION_ATTRIBUTES_TAG          = 0x01
+    JOB_ATTRIBUTES_TAG                = 0x02
+    END_OF_ATTRIBUTES_TAG             = 0x03
+    PRINTER_ATTRIBUTES_TAG            = 0x04
+    UNSUPPORTED_ATTRIBUTES_TAG        = 0x05
     
     # "out of band" value tags
-    UNSUPPORTED                       = 0X10
-    DEFAULT                           = 0X11
-    UNKNOWN                           = 0X12
-    NO_VALUE                          = 0X13
+    UNSUPPORTED                       = 0x10
+    DEFAULT                           = 0x11
+    UNKNOWN                           = 0x12
+    NO_VALUE                          = 0x13
     
     # integer value tags
-    GENERIC_INTEGER                   = 0X20
-    INTEGER                           = 0X21
-    BOOLEAN                           = 0X22
-    ENUM                              = 0X23
+    GENERIC_INTEGER                   = 0x20
+    INTEGER                           = 0x21
+    BOOLEAN                           = 0x22
+    ENUM                              = 0x23
 
     # octetstring value tags
-    UNSPECIFIED_OCTETSTRING           = 0X30
-    DATETIME                          = 0X31
-    RESOLUTION                        = 0X32
-    RANGEOFINTEGER                    = 0X33
-    COLLECTION                        = 0X34
-    TEXTWITHLANGUAGE                  = 0X35
-    NAMEWITHLANGUAGE                  = 0X36
+    UNSPECIFIED_OCTETSTRING           = 0x30
+    DATETIME                          = 0x31
+    RESOLUTION                        = 0x32
+    RANGEOFINTEGER                    = 0x33
+    COLLECTION                        = 0x34
+    TEXTWITHLANGUAGE                  = 0x35
+    NAMEWITHLANGUAGE                  = 0x36
 
     # character-string value tags
-    GENERIC_CHAR_STRING               = 0X40
-    TEXTWITHOUTLANGUAGE               = 0X41
-    NAMEWITHOUTLANGUAGE               = 0X42
-    KEYWORD                           = 0X44
-    URI                               = 0X45
-    URISCHEME                         = 0X46
-    CHARSET                           = 0X47
-    NATURALLANGUAGE                   = 0X48
-    MIMEMEDIATYPE                     = 0X49                                    
+    GENERIC_CHAR_STRING               = 0x40
+    TEXTWITHOUTLANGUAGE               = 0x41
+    NAMEWITHOUTLANGUAGE               = 0x42
+    KEYWORD                           = 0x44
+    URI                               = 0x45
+    URISCHEME                         = 0x46
+    CHARSET                           = 0x47
+    NATURALLANGUAGE                   = 0x48
+    MIMEMEDIATYPE                     = 0x49                                    
 
 class IPPValue():
     """
     An IPP value consists of a tag and a value, and optionally, a name.
+
+    From RFC 2565:
+     -----------------------------------------------
+     |                   value-tag                 |   1 byte
+     -----------------------------------------------
+     |               name-length  (value is u)     |   2 bytes
+     -----------------------------------------------
+     |                     name                    |   u bytes
+     -----------------------------------------------
+     |              value-length  (value is v)     |   2 bytes
+     -----------------------------------------------
+     |                     value                   |   v bytes
+     -----------------------------------------------    
     """
 
@@ -78,4 +91,32 @@
         self.name = str(name)
         self.value = str(value)
+
+    def toBinaryData(self):
+        """
+        Packs the value data into binary data.
+        """
+        
+        # get the length in bytes of the name
+        name_length = sys.getsizeof(name)
+        # get the length in bytes of the value
+        value_length = sys.getsizeof(value)
+
+        # if the name is of length zero, then don't include it in the
+        # binary data
+        if name_length == IPPTags.ZERO_NAME_LENGTH:
+            binary = struct.pack('>bhhs',
+                                 self.value_tag,
+                                 name_length,
+                                 value_length,
+                                 self.value)
+        else:
+            binary = struct.pack('>bhshs',
+                                 self.value_tag,
+                                 name_length,
+                                 self.name,
+                                 value_length,
+                                 self.value)
+
+        return binary
 
 class IPPAttribute():
@@ -135,4 +176,17 @@
          self.attribute_tag = hex(attribute_tag)
          self.values = values
+
+    def toBinaryData(self):
+        """
+        Packs the attribute data into binary data.
+        """
+
+        # pack the attribute tag
+        attribute_tag = struct.pack('>b', self.attribute_tag)
+        # get the binary data for all the values
+        values = [v.toBinaryData() for v in self.values]
+
+        # concatenate everything together and return it
+        return attribute_tag + ''.join(values)
 
 class IPPRequest():
@@ -216,12 +270,12 @@
         if request is not None:
             # read the version-number (two signed chars)
-            self.version        = struct.unpack('bb', request.read(2))
+            self.version        = struct.unpack('>bb', request.read(2))
 
             # read the operation-id (or status-code, but that's only
             # for a response) (signed short)
-            self.operation_id   = struct.unpack('h', request.read(2))
+            self.operation_id   = struct.unpack('>h', request.read(2))
 
             # read the request-id (signed int)
-            self.request_id     = struct.unpack('i', request.read(4))
+            self.request_id     = struct.unpack('>i', request.read(4))
 
             # now we have to read in the attributes.  Each attribute
@@ -230,5 +284,5 @@
 
             # read in the next byte
-            next_byte = struct.unpack('b', request.read(1))
+            next_byte = struct.unpack('>b', request.read(1))
 
             # as long as the next byte isn't signaling the end of the
@@ -242,13 +296,13 @@
                     attribute_tag = next_byte
                     # read in the value tag (signed char)
-                    value_tag     = struct.unpack('b', request.read(1))
+                    value_tag     = struct.unpack('>b', request.read(1))
                     # read in the length of the name (signed short)
-                    name_length   = struct.unpack('h', request.read(2))
+                    name_length   = struct.unpack('>h', request.read(2))
                     # read the name (a string of name_length bytes)
-                    name          = struct.unpack('s', request.read(name_length))
+                    name          = struct.unpack('>s', request.read(name_length))
                     # read in the length of the value (signed short)
-                    value_length  = struct.unpack('h', request.read(2))
+                    value_length  = struct.unpack('>h', request.read(2))
                     # read in the value (string of value_length bytes)
-                    value         = struct.unpack('b'*value_length, request.read(value_length))
+                    value         = struct.unpack('>%sb' % value_length, request.read(value_length))
 
                     # create a new IPPAttribute from the data we just
@@ -265,12 +319,12 @@
                     # read in the length of the name (two bytes) --
                     # this should be 0x0
-                    name_length   = struct.unpack('h', request.read(2))
-                    assert name_length == zero_name_length
+                    name_length   = struct.unpack('>h', request.read(2))
+                    assert name_length == IPPTags.ZERO_NAME_LENGTH
                     # name should be empty
                     name          = ''
                     # read in the length of the value (two bytes)
-                    value_length  = struct.unpack('h', request.read(2))
+                    value_length  = struct.unpack('>h', request.read(2))
                     # read in the value (value_length bytes)
-                    value         = struct.unpack('b'*value_length, request.read(value_length))
+                    value         = struct.unpack('>%sb' % value_length, request.read(value_length))
 
                     # add another value to the last attribute
@@ -278,10 +332,10 @@
 
                 # read another byte
-                next_byte = struct.unpack('b', request.read(1))
+                next_byte = struct.unpack('>b', request.read(1))
 
             # once we hit the end-of-attributes tag, the only thing
             # left is the data, so go ahead and read all of it
             buff = request.read()
-            self.data = struct.unpack('b'*len(buff), sys.getsizeof(buff))
+            self.data = struct.unpack('>%sb' % len(buff), sys.getsizeof(buff))
 
         # otherwise, just set the class variables to the keyword
@@ -293,2 +347,26 @@
             self.attributes = attributes
             self.data = data
+
+    def toBinaryData(self):
+        """
+        Packs the value data into binary data.
+        """
+
+        # convert the version, operation id, and request id to binary
+        preattributes = struct.pack('>bbhi',
+                                    self.version[0],
+                                    self.version[1],
+                                    self.operation_id,
+                                    self.request_id)
+
+        # convert the attributes to binary
+        attributes = ''.join([a.toBinaryData() for a in attributes])
+
+        # conver the end-of-attributes-tag to binary
+        end_of_attributes_tag = struct.pack('>b', IPPTags.END_OF_ATTRIBUTES_TAG)
+
+        # convert the data to binary
+        data = ''.join([struct.pack('>b', x) for x in self.data])
+
+        # append everything together and return it
+        return preattributes + attributes + end_of_attributes_tag + data
