root / pkpgcounter / trunk / pkpgpdls / lidil.py @ 488

Revision 488, 4.4 kB (checked in by jerome, 16 years ago)

Improved parser against cheaters, just in case.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1#! /usr/bin/env python
2# -*- coding: ISO-8859-15 -*-
3#
4# pkpgcounter : a generic Page Description Language parser
5#
6# (c) 2003, 2004, 2005, 2006, 2007 Jerome Alet <alet@librelogiciel.com>
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation, either version 3 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program.  If not, see <http://www.gnu.org/licenses/>.
19#
20# $Id$
21#
22
23"""This modules implements a page counter for HP LIDIL format.
24
25   Documentation used :
26   
27        hplip-2.7.10/prnt/ldl.py
28        hplip-2.7.10/prnt/hpijs/ldlencap.h
29"""
30
31import sys
32import os
33import mmap
34import struct
35
36import pdlparser
37
38# Packet types taken from hplip-2.7.10/prnt/ldl.py
39PACKET_TYPE_COMMAND = 0
40PACKET_TYPE_DISABLE_PACING = 1
41PACKET_TYPE_ENABLE_PACING = 2
42PACKET_TYPE_RESUME_NORMAL_OPERATION = 3
43PACKET_TYPE_DISABLE_RESPONSES = 4
44PACKET_TYPE_ENABLE_RESPONSES = 5
45PACKET_TYPE_RESET_LIDIL = 6
46PACKET_TYPE_SYNC = 7
47PACKET_TYPE_SYNC_COMPLETE = 8
48
49# Command codes we are interested in.
50LDL_LOAD_PAGE = 1
51LDL_EJECT_PAGE = 2
52
53class Parser(pdlparser.PDLParser) :
54    """A parser for HP LIDIL documents."""
55    def isValid(self) :   
56        """Returns True if data is LIDIL, else False."""
57        # Beginning Of File marker is a Sync packet, followed with
58        # a Sync Complete packet followed with a Reset packet.
59        # We just look at the start of the Sync packet for simplicity's sake.
60        BOFMarker = "$\x01\x00\x00\x07"
61        # End Of File marker is a Sync Complete packet followed
62        # with a Reset packet. We ignore the preceding Sync packet
63        # for simplicity's sake.
64        EOFMarker = "$\x00\x10\x00\x08\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff$$\x00\x10\x00\x06\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff$" 
65        if self.firstblock.startswith(BOFMarker) \
66           and self.lastblock.endswith(EOFMarker) :
67            self.logdebug("DEBUG: Input file is in the Hewlett-Packard LIDIL format.")
68            return True
69        else :   
70            return False
71       
72    def getJobSize(self) :
73        """Computes the number of pages in a HP LIDIL document."""
74        unpack = struct.unpack
75        ejectpage = loadpage = 0
76        infileno = self.infile.fileno()
77        minfile = mmap.mmap(infileno, os.fstat(infileno)[6], prot=mmap.PROT_READ, flags=mmap.MAP_SHARED)
78        pos = 0
79        try :
80            try :
81                while 1 :
82                    if minfile[pos] != "$" :    # Frame Sync
83                        raise pdlparser.PDLParserError, "This file doesn't seem to be valid Hewlett-Packard LIDIL datas"
84                    try :   
85                        (framesync,     
86                         cmdlength,
87                         dummy,
88                         packettype,
89                         commandnumber,
90                         referencenumber,
91                         datalength) = unpack(">BHBBBHH", minfile[pos:pos+10])
92                    except struct.error :   
93                        raise pdlparser.PDLParserError, "This file doesn't seem to be valid Hewlett-Packard LIDIL datas"
94                    if packettype == PACKET_TYPE_COMMAND :
95                        if commandnumber == LDL_LOAD_PAGE :
96                            loadpage += 1
97                        elif commandnumber == LDL_EJECT_PAGE :
98                            ejectpage += 1
99                    pos += (cmdlength + datalength)
100            except IndexError : # EOF ?
101                pass 
102        finally :       
103            minfile.close()
104           
105        # Number of page eject commands should be sufficient,
106        # but we never know : someone could try to cheat the printer
107        # by loading a page but not ejecting it, and ejecting it manually
108        # later on. Not sure if the printers would support this, but
109        # taking the max value works around the problem in any case.
110        self.logdebug("Load : %i    Eject : %i" % (loadpage, ejectpage))
111        return max(loadpage, ejectpage)
112
113if __name__ == "__main__" :   
114    pdlparser.test(Parser)
Note: See TracBrowser for help on using the browser.