source: server/lib/ipplib.py @ d56a0bc

no-cups
Last change on this file since d56a0bc was d56a0bc, checked in by Jessica B. Hamrick <jhamrick@…>, 13 years ago

Add toBinaryData functions in ipprequest.py; add ipplib.py for reference (unsupported)

  • Property mode set to 100755
File size: 19.3 KB
Line 
1#! /usr/bin/env python
2import sys,os,urllib2,socket
3from struct import pack, unpack
4
5IPP_VERSION = "1.1"
6
7IPP_PORT = 631
8
9IPP_MAX_NAME = 256
10IPP_MAX_VALUES = 8
11
12IPP_TAG_ZERO = 0x00
13IPP_TAG_OPERATION = 0x01
14IPP_TAG_JOB = 0x02
15IPP_TAG_END = 0x03
16IPP_TAG_PRINTER = 0x04
17IPP_TAG_UNSUPPORTED_GROUP = 0x05
18IPP_TAG_SUBSCRIPTION = 0x06
19IPP_TAG_EVENT_NOTIFICATION = 0x07
20IPP_TAG_UNSUPPORTED_VALUE = 0x10
21IPP_TAG_DEFAULT = 0x11
22IPP_TAG_UNKNOWN = 0x12
23IPP_TAG_NOVALUE = 0x13
24IPP_TAG_NOTSETTABLE = 0x15
25IPP_TAG_DELETEATTR = 0x16
26IPP_TAG_ADMINDEFINE = 0x17
27IPP_TAG_INTEGER = 0x21
28IPP_TAG_BOOLEAN = 0x22
29IPP_TAG_ENUM = 0x23
30IPP_TAG_STRING = 0x30
31IPP_TAG_DATE = 0x31
32IPP_TAG_RESOLUTION = 0x32
33IPP_TAG_RANGE = 0x33
34IPP_TAG_BEGIN_COLLECTION = 0x34
35IPP_TAG_TEXTLANG = 0x35
36IPP_TAG_NAMELANG = 0x36
37IPP_TAG_END_COLLECTION = 0x37
38IPP_TAG_TEXT = 0x41
39IPP_TAG_NAME = 0x42
40IPP_TAG_KEYWORD = 0x44
41IPP_TAG_URI = 0x45
42IPP_TAG_URISCHEME = 0x46
43IPP_TAG_CHARSET = 0x47
44IPP_TAG_LANGUAGE = 0x48
45IPP_TAG_MIMETYPE = 0x49
46IPP_TAG_MEMBERNAME = 0x4a
47IPP_TAG_MASK = 0x7fffffff
48IPP_TAG_COPY = -0x7fffffff-1
49
50IPP_RES_PER_INCH = 3
51IPP_RES_PER_CM = 4
52
53IPP_FINISHINGS_NONE = 3
54IPP_FINISHINGS_STAPLE = 4
55IPP_FINISHINGS_PUNCH = 5
56IPP_FINISHINGS_COVER = 6
57IPP_FINISHINGS_BIND = 7
58IPP_FINISHINGS_SADDLE_STITCH = 8
59IPP_FINISHINGS_EDGE_STITCH = 9
60IPP_FINISHINGS_FOLD = 10
61IPP_FINISHINGS_TRIM = 11
62IPP_FINISHINGS_BALE = 12
63IPP_FINISHINGS_BOOKLET_MAKER = 13
64IPP_FINISHINGS_JOB_OFFSET = 14
65IPP_FINISHINGS_STAPLE_TOP_LEFT = 20
66IPP_FINISHINGS_STAPLE_BOTTOM_LEFT = 21
67IPP_FINISHINGS_STAPLE_TOP_RIGHT = 22
68IPP_FINISHINGS_STAPLE_BOTTOM_RIGHT = 23
69IPP_FINISHINGS_EDGE_STITCH_LEFT = 24
70IPP_FINISHINGS_EDGE_STITCH_TOP = 25
71IPP_FINISHINGS_EDGE_STITCH_RIGHT = 26
72IPP_FINISHINGS_EDGE_STITCH_BOTTOM = 27
73IPP_FINISHINGS_STAPLE_DUAL_LEFT = 28
74IPP_FINISHINGS_STAPLE_DUAL_TOP = 29
75IPP_FINISHINGS_STAPLE_DUAL_RIGHT = 30
76IPP_FINISHINGS_STAPLE_DUAL_BOTTOM = 31
77IPP_FINISHINGS_BIND_LEFT = 50
78IPP_FINISHINGS_BIND_TOP = 51
79IPP_FINISHINGS_BIND_RIGHT = 52
80IPP_FINISHINGS_BIND_BOTTO = 53
81
82IPP_PORTRAIT = 3
83IPP_LANDSCAPE = 4
84IPP_REVERSE_LANDSCAPE = 5
85IPP_REVERSE_PORTRAIT = 6
86
87IPP_QUALITY_DRAFT = 3
88IPP_QUALITY_NORMAL = 4
89IPP_QUALITY_HIGH = 5
90
91IPP_JOB_PENDING = 3
92IPP_JOB_HELD = 4
93IPP_JOB_PROCESSING = 5
94IPP_JOB_STOPPED = 6
95IPP_JOB_CANCELLED = 7
96IPP_JOB_ABORTED = 8
97IPP_JOB_COMPLETE = 9
98
99IPP_PRINTER_IDLE = 3
100IPP_PRINTER_PROCESSING = 4
101IPP_PRINTER_STOPPED = 5
102
103IPP_ERROR = -1
104IPP_IDLE = 0
105IPP_HEADER = 1
106IPP_ATTRIBUTE = 2
107IPP_DATA = 3
108
109IPP_PRINT_JOB = 0x0002
110IPP_PRINT_URI = 0x0003
111IPP_VALIDATE_JOB = 0x0004
112IPP_CREATE_JOB = 0x0005
113IPP_SEND_DOCUMENT = 0x0006
114IPP_SEND_URI = 0x0007
115IPP_CANCEL_JOB = 0x0008
116IPP_GET_JOB_ATTRIBUTES = 0x0009
117IPP_GET_JOBS = 0x000a
118IPP_GET_PRINTER_ATTRIBUTES = 0x000b
119IPP_HOLD_JOB = 0x000c
120IPP_RELEASE_JOB = 0x000d
121IPP_RESTART_JOB = 0x000e
122IPP_PAUSE_PRINTER = 0x0010
123IPP_RESUME_PRINTER = 0x0011
124IPP_PURGE_JOBS = 0x0012
125IPP_SET_PRINTER_ATTRIBUTES = 0x0013
126IPP_SET_JOB_ATTRIBUTES = 0x0014
127IPP_GET_PRINTER_SUPPORTED_VALUES = 0x0015
128IPP_CREATE_PRINTER_SUBSCRIPTION = 0x0016
129IPP_CREATE_JOB_SUBSCRIPTION = 0x0017
130IPP_GET_SUBSCRIPTION_ATTRIBUTES = 0x0018
131IPP_GET_SUBSCRIPTIONS = 0x0019
132IPP_RENEW_SUBSCRIPTION = 0x001a
133IPP_CANCEL_SUBSCRIPTION = 0x001b
134IPP_GET_NOTIFICATIONS = 0x001c
135IPP_SEND_NOTIFICATIONS = 0x001d
136IPP_GET_PRINT_SUPPORT_FILES = 0x0021
137IPP_ENABLE_PRINTER = 0x0022
138IPP_DISABLE_PRINTER = 0x0023
139IPP_PAUSE_PRINTER_AFTER_CURRENT_JOB = 0x0024
140IPP_HOLD_NEW_JOBS = 0x0025
141IPP_RELEASE_HELD_NEW_JOBS = 0x0026
142IPP_DEACTIVATE_PRINTER = 0x0027
143IPP_ACTIVATE_PRINTER = 0x0028
144IPP_RESTART_PRINTER = 0x0029
145IPP_SHUTDOWN_PRINTER = 0x002a
146IPP_STARTUP_PRINTER = 0x002b
147IPP_REPROCESS_JOB = 0x002c
148IPP_CANCEL_CURRENT_JOB = 0x002d
149IPP_SUSPEND_CURRENT_JOB = 0x002e
150IPP_RESUME_JOB = 0x002f
151IPP_PROMOTE_JOB = 0x0030
152IPP_SCHEDULE_JOB_AFTER = 0x0031
153IPP_PRIVATE = 0x4000
154CUPS_GET_DEFAULT = 0x4001
155CUPS_GET_PRINTERS = 0x4002
156CUPS_ADD_PRINTER = 0x4003
157CUPS_DELETE_PRINTER = 0x4004
158CUPS_GET_CLASSES = 0x4005
159CUPS_ADD_CLASS = 0x4006
160CUPS_DELETE_CLASS = 0x4007
161CUPS_ACCEPT_JOBS = 0x4008
162CUPS_REJECT_JOBS = 0x4009
163CUPS_SET_DEFAULT = 0x400a
164CUPS_GET_DEVICES = 0x400b
165CUPS_GET_PPDS = 0x400c
166CUPS_MOVE_JOB = 0x400d
167CUPS_AUTHENTICATE_JOB = 0x400e
168
169IPP_OK = 0x0000
170IPP_OK_SUBST = 0x0001
171IPP_OK_CONFLICT = 0x0002
172IPP_OK_IGNORED_SUBSCRIPTIONS = 0x0003
173IPP_OK_IGNORED_NOTIFICATIONS = 0x0004
174IPP_OK_TOO_MANY_EVENTS = 0x0005
175IPP_OK_BUT_CANCEL_SUBSCRIPTION = 0x0006
176IPP_REDIRECTION_OTHER_SITE = 0x0300
177IPP_BAD_REQUEST = 0x0400
178IPP_FORBIDDEN = 0x0401
179IPP_NOT_AUTHENTICATED = 0x0402
180IPP_NOT_AUTHORIZED = 0x0403
181IPP_NOT_POSSIBLE = 0x0404
182IPP_TIMEOUT = 0x0405
183IPP_NOT_FOUND = 0x0406
184IPP_GONE = 0x0407
185IPP_REQUEST_ENTITY = 0x0408
186IPP_REQUEST_VALUE = 0x0409
187IPP_DOCUMENT_FORMAT = 0x040a
188IPP_ATTRIBUTES = 0x040b
189IPP_URI_SCHEME = 0x040c
190IPP_CHARSET = 0x040d
191IPP_CONFLICT = 0x040e
192IPP_COMPRESSION_NOT_SUPPORTED = 0x040f
193IPP_COMPRESSION_ERROR = 0x0410
194IPP_DOCUMENT_FORMAT_ERROR = 0x0411
195IPP_DOCUMENT_ACCESS_ERROR = 0x0412
196IPP_ATTRIBUTES_NOT_SETTABLE = 0x0413
197IPP_IGNORED_ALL_SUBSCRIPTIONS = 0x0414
198IPP_TOO_MANY_SUBSCRIPTIONS = 0x0415
199IPP_IGNORED_ALL_NOTIFICATIONS = 0x0416
200IPP_PRINT_SUPPORT_FILE_NOT_FOUND = 0x0417
201
202IPP_INTERNAL_ERROR = 0x0500
203IPP_OPERATION_NOT_SUPPORTED = 0x0501
204IPP_SERVICE_UNAVAILABLE = 0x0502
205IPP_VERSION_NOT_SUPPORTED = 0x0503
206IPP_DEVICE_ERROR = 0x0504
207IPP_TEMPORARY_ERROR = 0x0505
208IPP_NOT_ACCEPTING = 0x0506
209IPP_PRINTER_BUSY = 0x0507
210IPP_ERROR_JOB_CANCELLED = 0x0508
211IPP_MULTIPLE_JOBS_NOT_SUPPORTED = 0x0509
212IPP_PRINTER_IS_DEACTIVATED = 0x50a
213 
214CUPS_PRINTER_LOCAL = 0x0000
215CUPS_PRINTER_CLASS = 0x0001
216CUPS_PRINTER_REMOTE = 0x0002
217CUPS_PRINTER_BW = 0x0004
218CUPS_PRINTER_COLOR = 0x0008
219CUPS_PRINTER_DUPLEX = 0x0010
220CUPS_PRINTER_STAPLE = 0x0020
221CUPS_PRINTER_COPIES = 0x0040
222CUPS_PRINTER_COLLATE = 0x0080
223CUPS_PRINTER_PUNCH = 0x0100
224CUPS_PRINTER_COVER = 0x0200
225CUPS_PRINTER_BIND = 0x0400
226CUPS_PRINTER_SORT = 0x0800
227CUPS_PRINTER_SMALL = 0x1000
228CUPS_PRINTER_MEDIUM = 0x2000
229CUPS_PRINTER_LARGE = 0x4000
230CUPS_PRINTER_VARIABLE = 0x8000
231CUPS_PRINTER_IMPLICIT = 0x10000
232CUPS_PRINTER_DEFAULT = 0x20000
233CUPS_PRINTER_FAX = 0x40000
234CUPS_PRINTER_REJECTING = 0x80000
235CUPS_PRINTER_DELETE = 0x100000
236CUPS_PRINTER_NOT_SHARED = 0x200000
237CUPS_PRINTER_AUTHENTICATED = 0x400000
238CUPS_PRINTER_COMMANDS = 0x800000
239CUPS_PRINTER_OPTIONS = 0xe6ff
240 
241 
242class IPPError(Exception) :
243    """An exception for IPP related stuff."""
244    def __init__(self, message = ""):
245        self.message = message
246        Exception.__init__(self, message)
247    def __repr__(self):
248        return self.message
249    __str__ = __repr__
250
251class FakeAttribute :
252    """Fakes an IPPRequest attribute to simplify usage syntax."""
253    def __init__(self, request, name) :
254        """Initializes the fake attribute."""
255        self.request = request
256        self.name = name
257       
258    def __setitem__(self, key, value) :
259        """Appends the value to the real attribute."""
260        attributeslist = getattr(self.request, "_%s_attributes" % self.name)
261        for i in range(len(attributeslist)) :
262            attribute = attributeslist[i]
263            for j in range(len(attribute)) :
264                (attrname, attrvalue) = attribute[j]
265                if attrname == key :
266                    attribute[j][1].append(value)
267                    return
268            attribute.append((key, [value]))
269           
270    def __getitem__(self, key) :
271        """Returns an attribute's value."""
272        answer = []
273        attributeslist = getattr(self.request, "_%s_attributes" % self.name)
274        for i in range(len(attributeslist)) :
275            attribute = attributeslist[i]
276            for j in range(len(attribute)) :
277                (attrname, attrvalue) = attribute[j]
278                if attrname == key :
279                    answer.extend(attrvalue)
280        if answer :
281            return answer
282        raise KeyError, key
283   
284class IPPRequest :
285    """A class for IPP requests."""
286    attributes_types = ("operation", "job", "printer", "unsupported", \
287                                     "subscription", "event_notification")
288    def __init__(self, data="", version=IPP_VERSION,
289                                operation_id=None, \
290                                request_id=None, \
291                                debug=False) :
292        """Initializes an IPP Message object.
293       
294           Parameters :
295           
296             data : the complete IPP Message's content.
297             debug : a boolean value to output debug info on stderr.
298        """
299        self.debug = debug
300        self._data = data
301        self.parsed = False
302       
303        # Initializes message
304        self.setVersion(version)
305        self.setOperationId(operation_id)
306        self.setRequestId(request_id)
307        self.data = ""
308       
309        for attrtype in self.attributes_types :
310            setattr(self, "_%s_attributes" % attrtype, [[]])
311       
312        # Initialize tags   
313        self.tags = [ None ] * 256 # by default all tags reserved
314       
315        # Delimiter tags
316        self.tags[0x01] = "operation-attributes-tag"
317        self.tags[0x02] = "job-attributes-tag"
318        self.tags[0x03] = "end-of-attributes-tag"
319        self.tags[0x04] = "printer-attributes-tag"
320        self.tags[0x05] = "unsupported-attributes-tag"
321        self.tags[0x06] = "subscription-attributes-tag"
322        self.tags[0x07] = "event_notification-attributes-tag"
323       
324        # out of band values
325        self.tags[0x10] = "unsupported"
326        self.tags[0x11] = "reserved-for-future-default"
327        self.tags[0x12] = "unknown"
328        self.tags[0x13] = "no-value"
329        self.tags[0x15] = "not-settable"
330        self.tags[0x16] = "delete-attribute"
331        self.tags[0x17] = "admin-define"
332 
333        # integer values
334        self.tags[0x20] = "generic-integer"
335        self.tags[0x21] = "integer"
336        self.tags[0x22] = "boolean"
337        self.tags[0x23] = "enum"
338       
339        # octetString
340        self.tags[0x30] = "octetString-with-an-unspecified-format"
341        self.tags[0x31] = "dateTime"
342        self.tags[0x32] = "resolution"
343        self.tags[0x33] = "rangeOfInteger"
344        self.tags[0x34] = "begCollection"
345        self.tags[0x35] = "textWithLanguage"
346        self.tags[0x36] = "nameWithLanguage"
347        self.tags[0x37] = "endCollection"
348       
349        # character strings
350        self.tags[0x40] = "generic-character-string"
351        self.tags[0x41] = "textWithoutLanguage"
352        self.tags[0x42] = "nameWithoutLanguage"
353        self.tags[0x44] = "keyword"
354        self.tags[0x45] = "uri"
355        self.tags[0x46] = "uriScheme"
356        self.tags[0x47] = "charset"
357        self.tags[0x48] = "naturalLanguage"
358        self.tags[0x49] = "mimeMediaType"
359        self.tags[0x4a] = "memberAttrName"
360       
361        # Reverse mapping to generate IPP messages
362        self.tagvalues = {}
363        for i in range(len(self.tags)) :
364            value = self.tags[i]
365            if value is not None :
366                self.tagvalues[value] = i
367                                     
368    def __getattr__(self, name) :
369        """Fakes attribute access."""
370        if name in self.attributes_types :
371            return FakeAttribute(self, name)
372        else :
373            raise AttributeError, name
374           
375    def __str__(self) :
376        """Returns the parsed IPP message in a readable form."""
377        if not self.parsed :
378            return ""
379        mybuffer = []
380        mybuffer.append("IPP version : %s.%s" % self.version)
381        mybuffer.append("IPP operation Id : 0x%04x" % self.operation_id)
382        mybuffer.append("IPP request Id : 0x%08x" % self.request_id)
383        for attrtype in self.attributes_types :
384            for attribute in getattr(self, "_%s_attributes" % attrtype) :
385                if attribute :
386                    mybuffer.append("%s attributes :" % attrtype.title())
387                for (name, value) in attribute :
388                    mybuffer.append(%s : %s" % (name, value))
389        # if self.data :
390        #     mybuffer.append("IPP datas : %s" % repr(self.data))
391        return "\n".join(mybuffer)
392       
393    def logDebug(self, msg) :
394        """Prints a debug message."""
395        if self.debug :
396            sys.stderr.write("%s\n" % msg)
397            sys.stderr.flush()
398           
399    def setVersion(self, version) :
400        """Sets the request's operation id."""
401        if version is not None :
402            try :
403                self.version = [int(p) for p in version.split(".")]
404            except AttributeError :
405                if len(version) == 2 : # 2-tuple
406                    self.version = version
407                else :
408                    try :
409                        self.version = [int(p) for p in str(float(version)).split(".")]
410                    except :
411                        self.version = [int(p) for p in IPP_VERSION.split(".")]
412       
413    def setOperationId(self, opid) :
414        """Sets the request's operation id."""
415        self.operation_id = opid
416       
417    def setRequestId(self, reqid) :
418        """Sets the request's request id."""
419        self.request_id = reqid
420       
421    def dump(self) :
422        """Generates an IPP Message.
423       
424           Returns the message as a string of text.
425        """   
426        mybuffer = []
427        if None not in (self.version, self.operation_id) :
428            mybuffer.append(chr(self.version[0]) + chr(self.version[1]))
429            mybuffer.append(pack(">H", self.operation_id))
430            mybuffer.append(pack(">I", self.request_id or 1))
431            for attrtype in self.attributes_types :
432                for attribute in getattr(self, "_%s_attributes" % attrtype) :
433                    if attribute :
434                        mybuffer.append(chr(self.tagvalues["%s-attributes-tag" % attrtype]))
435                    for (attrname, value) in attribute :
436                        nameprinted = 0
437                        for (vtype, val) in value :
438                            mybuffer.append(chr(self.tagvalues[vtype]))
439                            if not nameprinted :
440                                mybuffer.append(pack(">H", len(attrname)))
441                                mybuffer.append(attrname)
442                                nameprinted = 1
443                            else :
444                                mybuffer.append(pack(">H", 0))
445                            if vtype in ("integer", "enum") :
446                                mybuffer.append(pack(">H", 4))
447                                mybuffer.append(pack(">I", val))
448                            elif vtype == "boolean" :
449                                mybuffer.append(pack(">H", 1))
450                                mybuffer.append(chr(val))
451                            else :
452                                mybuffer.append(pack(">H", len(val)))
453                                mybuffer.append(val)
454            mybuffer.append(chr(self.tagvalues["end-of-attributes-tag"]))
455        mybuffer.append(self.data)
456        return "".join(mybuffer)
457
458    def parse(self) :
459        """Parses an IPP Request.
460       
461           NB : Only a subset of RFC2910 is implemented.
462        """
463        self._curname = None
464        self._curattributes = None
465       
466        self.setVersion((ord(self._data[0]), ord(self._data[1])))
467        self.setOperationId(unpack(">H", self._data[2:4])[0])
468        self.setRequestId(unpack(">I", self._data[4:8])[0])
469        self.position = 8
470        endofattributes = self.tagvalues["end-of-attributes-tag"]
471        maxdelimiter = self.tagvalues["event_notification-attributes-tag"]
472        nulloffset = lambda : 0
473        #try :
474        if 1:
475            tag = ord(self._data[self.position])
476            while tag != endofattributes :
477                self.position += 1
478                name = self.tags[tag]
479                if name is not None :
480                    func = getattr(self, name.replace("-", "_"), nulloffset)
481                    self.position += func()
482                    if ord(self._data[self.position]) > maxdelimiter :
483                        self.position -= 1
484                        continue
485                oldtag = tag
486                tag = ord(self._data[self.position])
487                if tag == oldtag :
488                    self._curattributes.append([])
489        #except IndexError :
490        #    raise IPPError, "Unexpected end of IPP message."
491           
492        self.data = self._data[self.position+1:]
493        self.parsed = True
494       
495    def parseTag(self) :
496        """Extracts information from an IPP tag."""
497        pos = self.position
498        tagtype = self.tags[ord(self._data[pos])]
499        if tagtype == 'end-of-attributes-tag':
500            return 0
501        pos += 1
502        posend = pos2 = pos + 2
503        namelength = unpack(">H", self._data[pos:pos2])[0]
504        if not namelength :
505            name = self._curname
506        else :
507            posend += namelength
508            self._curname = name = self._data[pos2:posend]
509        pos2 = posend + 2
510        valuelength = unpack(">H", self._data[posend:pos2])[0]
511        posend = pos2 + valuelength
512        value = self._data[pos2:posend]
513        if tagtype in ("integer", "enum") :
514            value = unpack(">I", value)[0]
515        elif tagtype == "boolean" :
516            value = ord(value)
517        try :
518            (oldname, oldval) = self._curattributes[-1][-1]
519            if oldname == name :
520                oldval.append((tagtype, value))
521            else :
522                raise IndexError
523        except IndexError :
524            self._curattributes[-1].append((name, [(tagtype, value)]))
525        self.logDebug("%s(%s) : %s" % (name, tagtype, value))
526        return posend - self.position
527       
528    def operation_attributes_tag(self) :
529        """Indicates that the parser enters into an operation-attributes-tag group."""
530        self._curattributes = self._operation_attributes
531        return self.parseTag()
532       
533    def job_attributes_tag(self) :
534        """Indicates that the parser enters into a job-attributes-tag group."""
535        self._curattributes = self._job_attributes
536        return self.parseTag()
537       
538    def printer_attributes_tag(self) :
539        """Indicates that the parser enters into a printer-attributes-tag group."""
540        self._curattributes = self._printer_attributes
541        return self.parseTag()
542       
543    def unsupported_attributes_tag(self) :
544        """Indicates that the parser enters into an unsupported-attributes-tag group."""
545        self._curattributes = self._unsupported_attributes
546        return self.parseTag()
547       
548    def subscription_attributes_tag(self) :
549        """Indicates that the parser enters into a subscription-attributes-tag group."""
550        self._curattributes = self._subscription_attributes
551        return self.parseTag()
552       
553    def event_notification_attributes_tag(self) :
554        """Indicates that the parser enters into an event-notification-attributes-tag group."""
555        self._curattributes = self._event_notification_attributes
556        return self.parseTag()
557
558if __name__ == "__main__" :
559    if (len(sys.argv) < 2) or (sys.argv[1] == "--debug") :
560        print "usage : python pkipplib.py /var/spool/cups/c00005 [--debug] (for example)\n"
561    else :
562        infile = open(sys.argv[1], "rb")
563        filedata = infile.read()
564        infile.close()
565       
566        msg = IPPRequest(filedata, debug=(sys.argv[-1]=="--debug"))
567        msg.parse()
568        msg2 = IPPRequest(msg.dump())
569        msg2.parse()
570        filedata2 = msg2.dump()
571       
572        if filedata == filedata2 :
573            print "Test OK : parsing original and parsing the output of the dump produce the same dump !"
574            print str(msg)
575        else :
576            print "Test Failed !"
577            print str(msg)
578            print
579            print str(msg2)
Note: See TracBrowser for help on using the repository browser.