Index: server/lib/ippattribute.py
===================================================================
--- server/lib/ippattribute.py	(revision 8979f907286779f8921e644f8f04b23cc89b0a73)
+++ server/lib/ippattribute.py	(revision 8979f907286779f8921e644f8f04b23cc89b0a73)
@@ -0,0 +1,112 @@
+#!/usr/bin/python
+
+import sys, struct, logging
+
+# initialize logger
+logger = logging.getLogger("ippLogger")
+
+class IPPAttribute():
+    """
+    In addition to what the RFC reports, an attribute has an
+    'attribute tag', which specifies what type of attribute it is.
+    It is 1 bytes long, and comes before the list of values.
+
+    From RFC 2565:
+
+    Each attribute consists of:
+    -----------------------------------------------
+    |                   value-tag                 |   1 byte
+    -----------------------------------------------
+    |               name-length  (value is u)     |   2 bytes
+    -----------------------------------------------
+    |                     name                    |   u bytes
+    -----------------------------------------------
+    |              value-length  (value is v)     |   2 bytes
+    -----------------------------------------------
+    |                     value                   |   v bytes
+    -----------------------------------------------
+
+    An additional value consists of:
+    -----------------------------------------------------------
+    |                   value-tag                 |   1 byte  |
+    -----------------------------------------------           |
+    |            name-length  (value is 0x0000)   |   2 bytes |
+    -----------------------------------------------           |-0 or more
+    |              value-length (value is w)      |   2 bytes |
+    -----------------------------------------------           |
+    |                     value                   |   w bytes |
+    -----------------------------------------------------------
+    """
+
+    def __init__(self, name, values):
+        """
+        Initialize an IPPAttribute.
+        
+        Arguments:
+
+            name -- the name of the attribute
+
+            values -- a list of IPPValues.  May not be empty.
+        """
+
+        # make sure name isn't empty
+        assert name is not None
+         
+        # make sure the list of values isn't empty
+        assert len(values) > 0
+        # make sure each value is an IPPValue
+        for value in values: assert isinstance(value, IPPValue)
+         
+        self.name = name
+        self.values = values
+
+    def toBinaryData(self):
+        """
+        Packs the attribute data into binary data.
+        """
+
+        # get the binary data for all the values
+        values = []
+        for v, i in zip(self.values, xrange(len(self.values))):
+
+            # get the name length (0 for everything but the first
+            # value)
+            if i == 0:
+                name_length = len(self.name)
+            else:
+                name_length = 0
+
+            # get the value length and binary value
+            value_length, value_bin = v.valueToBinary()
+
+            logger.debug("dumping name_length : %i" % name_length)
+            logger.debug("dumping name : %s" % self.name)
+            logger.debug("dumping value_length : %i" % value_length)
+            logger.debug("dumping value : %s" % v.value)
+
+            # the value tag in binary
+            value_tag_bin = struct.pack('>b', v.value_tag)
+
+            # the name length in binary
+            name_length_bin = struct.pack('>h', name_length)
+
+            # the name in binary
+            name_bin = self.name
+
+            # the value length in binary
+            value_length_bin = struct.pack('>h', value_length)
+
+            if i == 0:
+                values.append(''.join([value_tag_bin,
+                                       name_length_bin,
+                                       name_bin,
+                                       value_length_bin,
+                                       value_bin]))
+            else:
+                values.append(''.join([value_tag_bin,
+                                       name_length_bin,
+                                       value_length_bin,
+                                       value_bin]))
+                
+        # concatenate everything together and return it
+        return ''.join(values)
Index: server/lib/ippattributegroup.py
===================================================================
--- server/lib/ippattributegroup.py	(revision 8979f907286779f8921e644f8f04b23cc89b0a73)
+++ server/lib/ippattributegroup.py	(revision 8979f907286779f8921e644f8f04b23cc89b0a73)
@@ -0,0 +1,51 @@
+#!/usr/bin/python
+
+import sys, struct, logging
+
+# initialize logger
+logger = logging.getLogger("ippLogger")
+
+class IPPAttributeGroup():
+    """
+    An IPPAttributeGroup consists of an attribute-group-tag, followed
+    by a sequence of IPPAttributes.
+    """
+
+    def __init__(self, attribute_group_tag, attributes=[]):
+        """
+        Initialize an IPPAttributeGroup.
+
+        Arguments:
+
+            attribute_group_tag -- a signed char, holds the tag of the
+                                   attribute group
+
+            attributes -- (optional) a list of attributes
+        """
+
+        # make sure attribute_group_tag isn't empty
+        assert attribute_group_tag is not None
+
+        # make sure attributes is a list or tuple of IPPAttributes
+        assert isinstance(attributes, (list, tuple))
+        for a in attributes: assert isinstance(a, IPPAttribute)
+
+        self.attribute_group_tag = attribute_group_tag
+        self.attributes = attributes
+
+    def getAttribute(self, name):
+        return filter(lambda x: x.name == name, self.attributes)
+
+    def toBinaryData(self):
+        """
+        Convert the IPPAttributeGroup to binary.
+        """
+
+        # conver the attribute_group_tag to binary
+        tag = struct.pack('>b', self.attribute_group_tag)
+
+        # convert each of the attributes to binary
+        attributes = [a.toBinaryData() for a in self.attributes]
+
+        # concatenate everything and return
+        return tag + ''.join(attributes)
Index: server/lib/ippconstants.py
===================================================================
--- server/lib/ippconstants.py	(revision e97c37d3601faadfc986a1120f8b6224887e7c6b)
+++ server/lib/ippconstants.py	(revision 8979f907286779f8921e644f8f04b23cc89b0a73)
@@ -1,2 +1,4 @@
+#!/usr/bin/python
+
 class Misc():
     """
Index: server/lib/ipprequest.py
===================================================================
--- server/lib/ipprequest.py	(revision c5e88d0c6716914a8804748ab122258f3870dbf6)
+++ server/lib/ipprequest.py	(revision 8979f907286779f8921e644f8f04b23cc89b0a73)
@@ -5,395 +5,4 @@
 # initialize logger
 logger = logging.getLogger("ippLogger")
-
-class IPPTags():
-    """
-    Contains constants for the various IPP tags, as defined by RFC
-    2565.
-    """
-    
-    # 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
-    
-    # "out of band" value tags
-    UNSUPPORTED                       = 0x10
-    DEFAULT                           = 0x11
-    UNKNOWN                           = 0x12
-    NO_VALUE                          = 0x13
-    
-    # integer value tags
-    GENERIC_INTEGER                   = 0x20
-    INTEGER                           = 0x21
-    BOOLEAN                           = 0x22
-    ENUM                              = 0x23
-
-    # octetstring value tags
-    UNSPECIFIED_OCTETSTRING           = 0x30
-    DATETIME                          = 0x31
-    RESOLUTION                        = 0x32
-    RANGE_OF_INTEGER                  = 0x33
-    TEXT_WITH_LANGUAGE                = 0x35
-    NAME_WITH_LANGUAGE                = 0x36
-
-    # character-string value tags
-    GENERIC_CHAR_STRING               = 0x40
-    TEXT_WITHOUT_LANGUAGE             = 0x41
-    NAME_WITHOUT_LANGUAGE             = 0x42
-    KEYWORD                           = 0x44
-    URI                               = 0x45
-    URI_SCHEME                        = 0x46
-    CHARSET                           = 0x47
-    NATURAL_LANGUAGE                  = 0x48
-    MIME_MEDIA_TYPE                   = 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
-     -----------------------------------------------    
-    """
-
-    def __init__(self, value_tag, value, unpack=True):
-        """
-        Initialize an IPPValue:
-
-        Arguments:
-
-            value_tag -- one byte, identifying the type of value
-
-            value -- variable size, containing the actual value
-        """
-
-        # make sure value_tag isn't empty
-        assert value_tag is not None
-        # make sure value isn't empty
-        assert value is not None
-
-        self.value_tag = value_tag
-        self.value = value
-
-        if not unpack: return
-
-        # out-of-band value tags
-        if self.value_tag == IPPTags.UNSUPPORTED or \
-               self.value_tag == IPPTags.DEFAULT or \
-               self.value_tag == IPPTags.UNKNOWN or \
-               self.value_tag == IPPTags.NO_VALUE:
-            self.value = ''
-
-        # integer value tags
-        elif self.value_tag == IPPTags.GENERIC_INTEGER:
-            pass # not supported
-        elif self.value_tag == IPPTags.INTEGER:
-            self.value = struct.unpack('>i', value)[0]
-        elif self.value_tag == IPPTags.BOOLEAN:
-            self.value = struct.unpack('>?', value)[0]
-        elif self.value_tag == IPPTags.ENUM:
-            self.value = struct.unpack('>i', value)[0]
-
-        # octet string value tags
-        elif self.value_tag == IPPTags.UNSPECIFIED_OCTETSTRING:
-            pass
-        
-        elif self.value_tag == IPPTags.DATETIME:
-            # field  octets  contents                  range
-            # -----  ------  --------                  -----
-            #   1      1-2   year                      0..65536
-            #   2       3    month                     1..12
-            #   3       4    day                       1..31
-            #   4       5    hour                      0..23
-            #   5       6    minutes                   0..59
-            #   6       7    seconds                   0..60
-            #                (use 60 for leap-second)
-            #   7       8    deci-seconds              0..9
-            #   8       9    direction from UTC        '+' / '-'
-            #   9      10    hours from UTC            0..11
-            #  10      11    minutes from UTC          0..59
-
-            self.value = struct.unpack('>hbbbbbbcbb', value)[0]
-            
-        elif self.value_tag == IPPTags.RESOLUTION:
-            # OCTET-STRING consisting of nine octets of 2
-            # SIGNED-INTEGERs followed by a SIGNED-BYTE. The first
-            # SIGNED-INTEGER contains the value of cross feed
-            # direction resolution. The second SIGNED-INTEGER contains
-            # the value of feed direction resolution. The SIGNED-BYTE
-            # contains the units
-
-            self.value = struct.unpack('>iib', value)
-            
-        elif self.value_tag == IPPTags.RANGE_OF_INTEGER:
-            # Eight octets consisting of 2 SIGNED-INTEGERs.  The first
-            # SIGNED-INTEGER contains the lower bound and the second
-            # SIGNED-INTEGER contains the upper bound.
-
-            self.value = struct.unpack('>ii', value)
-
-        elif self.value_tag == IPPTags.TEXT_WITH_LANGUAGE or \
-                 self.value_tag == IPPTags.NAME_WITH_LANGUAGE:
-            a = struct.unpack('>h', value[:2])[0]
-            b = struct.unpack('>%ss' % a, value[2:a+2])[0]
-            c = struct.unpack('>h', value[a+2:a+4])[0]
-            d = struct.unpack('>%ss' % c, value[a+4:][0])
-            self.value = (a, b, c, d)
-
-        # character string value tags
-        elif self.value_tag == IPPTags.TEXT_WITHOUT_LANGUAGE or \
-                 self.value_tag == IPPTags.NAME_WITHOUT_LANGUAGE:
-            self.value = str(value)
-        elif self.value_tag == IPPTags.GENERIC_CHAR_STRING or \
-                 self.value_tag == IPPTags.KEYWORD or \
-                 self.value_tag == IPPTags.URI or \
-                 self.value_tag == IPPTags.URI_SCHEME or \
-                 self.value_tag == IPPTags.CHARSET or \
-                 self.value_tag == IPPTags.NATURAL_LANGUAGE or \
-                 self.value_tag == IPPTags.MIME_MEDIA_TYPE:
-            self.value = str(value)
-
-    def valueToBinary(self):
-
-        # out-of-band value tags
-        if self.value_tag == IPPTags.UNSUPPORTED or \
-               self.value_tag == IPPTags.DEFAULT or \
-               self.value_tag == IPPTags.UNKNOWN or \
-               self.value_tag == IPPTags.NO_VALUE:
-            return (0, '')
-
-        # integer value tags
-        elif self.value_tag == IPPTags.GENERIC_INTEGER:
-            pass
-        elif self.value_tag == IPPTags.INTEGER:
-            return (4, struct.pack('>i', self.value))
-        elif self.value_tag == IPPTags.BOOLEAN:
-            return (1, struct.pack('>?', self.value))
-        elif self.value_tag == IPPTags.ENUM:
-            return (4, struct.pack('>i', self.value))
-
-        # octet string value tags
-        elif self.value_tag == IPPTags.UNSPECIFIED_OCTETSTRING:
-            pass
-        elif self.value_tag == IPPTags.DATETIME:
-            # field  octets  contents                  range
-            # -----  ------  --------                  -----
-            #   1      1-2   year                      0..65536
-            #   2       3    month                     1..12
-            #   3       4    day                       1..31
-            #   4       5    hour                      0..23
-            #   5       6    minutes                   0..59
-            #   6       7    seconds                   0..60
-            #                (use 60 for leap-second)
-            #   7       8    deci-seconds              0..9
-            #   8       9    direction from UTC        '+' / '-'
-            #   9      10    hours from UTC            0..11
-            #  10      11    minutes from UTC          0..59
-            
-            return (11, struct.pack('>hbbbbbbcbb', self.value))
-            
-        elif self.value_tag == IPPTags.RESOLUTION:
-            # OCTET-STRING consisting of nine octets of 2
-            # SIGNED-INTEGERs followed by a SIGNED-BYTE. The first
-            # SIGNED-INTEGER contains the value of cross feed
-            # direction resolution. The second SIGNED-INTEGER contains
-            # the value of feed direction resolution. The SIGNED-BYTE
-            # contains the units
-            
-            return (9, struct.pack('>iib', self.value))
-            
-        elif self.value_tag == IPPTags.RANGE_OF_INTEGER:
-            # Eight octets consisting of 2 SIGNED-INTEGERs.  The first
-            # SIGNED-INTEGER contains the lower bound and the second
-            # SIGNED-INTEGER contains the upper bound.
-            
-            return (8, struct.pack('>ii', self.value))
-
-        elif self.value_tag == IPPTags.TEXT_WITH_LANGUAGE or \
-                 self.value_tag == IPPTags.NAME_WITH_LANGUAGE:
-            a_bin = struct.pack('>h', self.value[0])
-            b_bin = struct.pack('>%ss' % self.value[0], self.value[1])
-            c_bin = struct.pack('>h', self.value[2])
-            d_bin = struct.pack('>%ss' % self.value[2], self.value[3])
-            return (4 + self.value[0] + self.value[2],
-                    a_bin + b_bin + c_bin + d_bin)
-
-        # character string value tags
-        elif self.value_tag == IPPTags.TEXT_WITHOUT_LANGUAGE or \
-                 self.value_tag == IPPTags.NAME_WITHOUT_LANGUAGE:
-            return (len(self.value), struct.pack('>%ss' % len(self.value), self.value))
-        elif self.value_tag == IPPTags.GENERIC_CHAR_STRING or \
-                 self.value_tag == IPPTags.KEYWORD or \
-                 self.value_tag == IPPTags.URI or \
-                 self.value_tag == IPPTags.URI_SCHEME or \
-                 self.value_tag == IPPTags.CHARSET or \
-                 self.value_tag == IPPTags.NATURAL_LANGUAGE or \
-                 self.value_tag == IPPTags.MIME_MEDIA_TYPE:
-            return (len(self.value), struct.pack('>%ss' % len(self.value), self.value))
-
-        return len(self.value), self.value
-
-class IPPAttribute():
-    """
-    In addition to what the RFC reports, an attribute has an
-    'attribute tag', which specifies what type of attribute it is.
-    It is 1 bytes long, and comes before the list of values.
-
-    From RFC 2565:
-
-    Each attribute consists of:
-    -----------------------------------------------
-    |                   value-tag                 |   1 byte
-    -----------------------------------------------
-    |               name-length  (value is u)     |   2 bytes
-    -----------------------------------------------
-    |                     name                    |   u bytes
-    -----------------------------------------------
-    |              value-length  (value is v)     |   2 bytes
-    -----------------------------------------------
-    |                     value                   |   v bytes
-    -----------------------------------------------
-
-    An additional value consists of:
-    -----------------------------------------------------------
-    |                   value-tag                 |   1 byte  |
-    -----------------------------------------------           |
-    |            name-length  (value is 0x0000)   |   2 bytes |
-    -----------------------------------------------           |-0 or more
-    |              value-length (value is w)      |   2 bytes |
-    -----------------------------------------------           |
-    |                     value                   |   w bytes |
-    -----------------------------------------------------------
-    """
-
-    def __init__(self, name, values):
-        """
-        Initialize an IPPAttribute.
-        
-        Arguments:
-
-            name -- the name of the attribute
-
-            values -- a list of IPPValues.  May not be empty.
-        """
-
-        # make sure name isn't empty
-        assert name is not None
-         
-        # make sure the list of values isn't empty
-        assert len(values) > 0
-        # make sure each value is an IPPValue
-        for value in values: assert isinstance(value, IPPValue)
-         
-        self.name = name
-        self.values = values
-
-    def toBinaryData(self):
-        """
-        Packs the attribute data into binary data.
-        """
-
-        # get the binary data for all the values
-        values = []
-        for v, i in zip(self.values, xrange(len(self.values))):
-
-            # get the name length (0 for everything but the first
-            # value)
-            if i == 0:
-                name_length = len(self.name)
-            else:
-                name_length = 0
-
-            # get the value length and binary value
-            value_length, value_bin = v.valueToBinary()
-
-            logger.debug("dumping name_length : %i" % name_length)
-            logger.debug("dumping name : %s" % self.name)
-            logger.debug("dumping value_length : %i" % value_length)
-            logger.debug("dumping value : %s" % v.value)
-
-            # the value tag in binary
-            value_tag_bin = struct.pack('>b', v.value_tag)
-
-            # the name length in binary
-            name_length_bin = struct.pack('>h', name_length)
-
-            # the name in binary
-            name_bin = self.name
-
-            # the value length in binary
-            value_length_bin = struct.pack('>h', value_length)
-
-            if i == 0:
-                values.append(''.join([value_tag_bin,
-                                       name_length_bin,
-                                       name_bin,
-                                       value_length_bin,
-                                       value_bin]))
-            else:
-                values.append(''.join([value_tag_bin,
-                                       name_length_bin,
-                                       value_length_bin,
-                                       value_bin]))
-                
-        # concatenate everything together and return it
-        return ''.join(values)
-
-class IPPAttributeGroup():
-    """
-    An IPPAttributeGroup consists of an attribute-group-tag, followed
-    by a sequence of IPPAttributes.
-    """
-
-    def __init__(self, attribute_group_tag, attributes=[]):
-        """
-        Initialize an IPPAttributeGroup.
-
-        Arguments:
-
-            attribute_group_tag -- a signed char, holds the tag of the
-                                   attribute group
-
-            attributes -- (optional) a list of attributes
-        """
-
-        # make sure attribute_group_tag isn't empty
-        assert attribute_group_tag is not None
-
-        # make sure attributes is a list or tuple of IPPAttributes
-        assert isinstance(attributes, (list, tuple))
-        for a in attributes: assert isinstance(a, IPPAttribute)
-
-        self.attribute_group_tag = attribute_group_tag
-        self.attributes = attributes
-
-    def getAttribute(self, name):
-        return filter(lambda x: x.name == name, self.attributes)
-
-    def toBinaryData(self):
-        """
-        Convert the IPPAttributeGroup to binary.
-        """
-
-        # conver the attribute_group_tag to binary
-        tag = struct.pack('>b', self.attribute_group_tag)
-
-        # convert each of the attributes to binary
-        attributes = [a.toBinaryData() for a in self.attributes]
-
-        # concatenate everything and return
-        return tag + ''.join(attributes)
 
 class IPPRequest():
Index: server/lib/ippvalue.py
===================================================================
--- server/lib/ippvalue.py	(revision 8979f907286779f8921e644f8f04b23cc89b0a73)
+++ server/lib/ippvalue.py	(revision 8979f907286779f8921e644f8f04b23cc89b0a73)
@@ -0,0 +1,201 @@
+#!/usr/bin/python
+
+import sys, struct, logging
+
+# initialize logger
+logger = logging.getLogger("ippLogger")
+
+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
+     -----------------------------------------------    
+    """
+
+    def __init__(self, value_tag, value, unpack=True):
+        """
+        Initialize an IPPValue:
+
+        Arguments:
+
+            value_tag -- one byte, identifying the type of value
+
+            value -- variable size, containing the actual value
+        """
+
+        # make sure value_tag isn't empty
+        assert value_tag is not None
+        # make sure value isn't empty
+        assert value is not None
+
+        self.value_tag = value_tag
+        self.value = value
+
+        if not unpack: return
+
+        # out-of-band value tags
+        if self.value_tag == IPPTags.UNSUPPORTED or \
+               self.value_tag == IPPTags.DEFAULT or \
+               self.value_tag == IPPTags.UNKNOWN or \
+               self.value_tag == IPPTags.NO_VALUE:
+            self.value = ''
+
+        # integer value tags
+        elif self.value_tag == IPPTags.GENERIC_INTEGER:
+            pass # not supported
+        elif self.value_tag == IPPTags.INTEGER:
+            self.value = struct.unpack('>i', value)[0]
+        elif self.value_tag == IPPTags.BOOLEAN:
+            self.value = struct.unpack('>?', value)[0]
+        elif self.value_tag == IPPTags.ENUM:
+            self.value = struct.unpack('>i', value)[0]
+
+        # octet string value tags
+        elif self.value_tag == IPPTags.UNSPECIFIED_OCTETSTRING:
+            pass
+        
+        elif self.value_tag == IPPTags.DATETIME:
+            # field  octets  contents                  range
+            # -----  ------  --------                  -----
+            #   1      1-2   year                      0..65536
+            #   2       3    month                     1..12
+            #   3       4    day                       1..31
+            #   4       5    hour                      0..23
+            #   5       6    minutes                   0..59
+            #   6       7    seconds                   0..60
+            #                (use 60 for leap-second)
+            #   7       8    deci-seconds              0..9
+            #   8       9    direction from UTC        '+' / '-'
+            #   9      10    hours from UTC            0..11
+            #  10      11    minutes from UTC          0..59
+
+            self.value = struct.unpack('>hbbbbbbcbb', value)[0]
+            
+        elif self.value_tag == IPPTags.RESOLUTION:
+            # OCTET-STRING consisting of nine octets of 2
+            # SIGNED-INTEGERs followed by a SIGNED-BYTE. The first
+            # SIGNED-INTEGER contains the value of cross feed
+            # direction resolution. The second SIGNED-INTEGER contains
+            # the value of feed direction resolution. The SIGNED-BYTE
+            # contains the units
+
+            self.value = struct.unpack('>iib', value)
+            
+        elif self.value_tag == IPPTags.RANGE_OF_INTEGER:
+            # Eight octets consisting of 2 SIGNED-INTEGERs.  The first
+            # SIGNED-INTEGER contains the lower bound and the second
+            # SIGNED-INTEGER contains the upper bound.
+
+            self.value = struct.unpack('>ii', value)
+
+        elif self.value_tag == IPPTags.TEXT_WITH_LANGUAGE or \
+                 self.value_tag == IPPTags.NAME_WITH_LANGUAGE:
+            a = struct.unpack('>h', value[:2])[0]
+            b = struct.unpack('>%ss' % a, value[2:a+2])[0]
+            c = struct.unpack('>h', value[a+2:a+4])[0]
+            d = struct.unpack('>%ss' % c, value[a+4:][0])
+            self.value = (a, b, c, d)
+
+        # character string value tags
+        elif self.value_tag == IPPTags.TEXT_WITHOUT_LANGUAGE or \
+                 self.value_tag == IPPTags.NAME_WITHOUT_LANGUAGE:
+            self.value = str(value)
+        elif self.value_tag == IPPTags.GENERIC_CHAR_STRING or \
+                 self.value_tag == IPPTags.KEYWORD or \
+                 self.value_tag == IPPTags.URI or \
+                 self.value_tag == IPPTags.URI_SCHEME or \
+                 self.value_tag == IPPTags.CHARSET or \
+                 self.value_tag == IPPTags.NATURAL_LANGUAGE or \
+                 self.value_tag == IPPTags.MIME_MEDIA_TYPE:
+            self.value = str(value)
+
+    def valueToBinary(self):
+
+        # out-of-band value tags
+        if self.value_tag == IPPTags.UNSUPPORTED or \
+               self.value_tag == IPPTags.DEFAULT or \
+               self.value_tag == IPPTags.UNKNOWN or \
+               self.value_tag == IPPTags.NO_VALUE:
+            return (0, '')
+
+        # integer value tags
+        elif self.value_tag == IPPTags.GENERIC_INTEGER:
+            pass
+        elif self.value_tag == IPPTags.INTEGER:
+            return (4, struct.pack('>i', self.value))
+        elif self.value_tag == IPPTags.BOOLEAN:
+            return (1, struct.pack('>?', self.value))
+        elif self.value_tag == IPPTags.ENUM:
+            return (4, struct.pack('>i', self.value))
+
+        # octet string value tags
+        elif self.value_tag == IPPTags.UNSPECIFIED_OCTETSTRING:
+            pass
+        elif self.value_tag == IPPTags.DATETIME:
+            # field  octets  contents                  range
+            # -----  ------  --------                  -----
+            #   1      1-2   year                      0..65536
+            #   2       3    month                     1..12
+            #   3       4    day                       1..31
+            #   4       5    hour                      0..23
+            #   5       6    minutes                   0..59
+            #   6       7    seconds                   0..60
+            #                (use 60 for leap-second)
+            #   7       8    deci-seconds              0..9
+            #   8       9    direction from UTC        '+' / '-'
+            #   9      10    hours from UTC            0..11
+            #  10      11    minutes from UTC          0..59
+            
+            return (11, struct.pack('>hbbbbbbcbb', self.value))
+            
+        elif self.value_tag == IPPTags.RESOLUTION:
+            # OCTET-STRING consisting of nine octets of 2
+            # SIGNED-INTEGERs followed by a SIGNED-BYTE. The first
+            # SIGNED-INTEGER contains the value of cross feed
+            # direction resolution. The second SIGNED-INTEGER contains
+            # the value of feed direction resolution. The SIGNED-BYTE
+            # contains the units
+            
+            return (9, struct.pack('>iib', self.value))
+            
+        elif self.value_tag == IPPTags.RANGE_OF_INTEGER:
+            # Eight octets consisting of 2 SIGNED-INTEGERs.  The first
+            # SIGNED-INTEGER contains the lower bound and the second
+            # SIGNED-INTEGER contains the upper bound.
+            
+            return (8, struct.pack('>ii', self.value))
+
+        elif self.value_tag == IPPTags.TEXT_WITH_LANGUAGE or \
+                 self.value_tag == IPPTags.NAME_WITH_LANGUAGE:
+            a_bin = struct.pack('>h', self.value[0])
+            b_bin = struct.pack('>%ss' % self.value[0], self.value[1])
+            c_bin = struct.pack('>h', self.value[2])
+            d_bin = struct.pack('>%ss' % self.value[2], self.value[3])
+            return (4 + self.value[0] + self.value[2],
+                    a_bin + b_bin + c_bin + d_bin)
+
+        # character string value tags
+        elif self.value_tag == IPPTags.TEXT_WITHOUT_LANGUAGE or \
+                 self.value_tag == IPPTags.NAME_WITHOUT_LANGUAGE:
+            return (len(self.value), struct.pack('>%ss' % len(self.value), self.value))
+        elif self.value_tag == IPPTags.GENERIC_CHAR_STRING or \
+                 self.value_tag == IPPTags.KEYWORD or \
+                 self.value_tag == IPPTags.URI or \
+                 self.value_tag == IPPTags.URI_SCHEME or \
+                 self.value_tag == IPPTags.CHARSET or \
+                 self.value_tag == IPPTags.NATURAL_LANGUAGE or \
+                 self.value_tag == IPPTags.MIME_MEDIA_TYPE:
+            return (len(self.value), struct.pack('>%ss' % len(self.value), self.value))
+
+        return len(self.value), self.value
