root / pykota / trunk / bin / pkpgcounter @ 1447

Revision 1447, 5.2 kB (checked in by jalet, 21 years ago)

fixed copy&paste problem in pkpgcounter

  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
Line 
1#! /usr/bin/env python
2# -*- coding: ISO-8859-15 -*-
3
4# pkpgcounter, a smart software page counter
5#
6# PyKota - Print Quotas for CUPS and LPRng
7#
8# (c) 2003-2004 Jerome Alet <alet@librelogiciel.com>
9# This program is free software; you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation; either version 2 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program; if not, write to the Free Software
21# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
22#
23# $Id$
24#
25# $Log$
26# Revision 1.2  2004/05/04 03:14:26  jalet
27# fixed copy&paste problem in pkpgcounter
28#
29# Revision 1.1  2004/04/08 17:07:42  jalet
30# pkpgcounter added
31#
32#
33
34import sys
35import tempfile
36
37def ispostscript(data) :   
38    """Returns 1 if data is PostScript, else 0."""
39    if data.startswith("%!") or \
40       data.startswith("\004%!") or \
41       data.startswith("\033%-12345X%!PS") or \
42       ((data[:128].find("\033%-12345X") != -1) and \
43         ((data.find("LANGUAGE=POSTSCRIPT") != -1) or \
44          (data.find("LANGUAGE = POSTSCRIPT") != -1) or \
45          (data.find("LANGUAGE = Postscript") != -1))) :
46        return 1
47    else :   
48        return 0
49   
50def postscript(infile) :
51    """Count pages in a PostScript document."""
52    pagecount = 0
53    pagenum = None
54    while 1 :
55        line = infile.readline()
56        if not line :
57            break
58        if line.startswith("%%Page: ") :
59            pagecount += 1
60    return pagecount
61   
62def ispcl(data) :   
63    """Returns 1 if data is PCL, else 0."""
64    if data.startswith("\033E\033") or \
65       ((data[:128].find("\033%-12345X") != -1) and \
66         ((data.find("LANGUAGE=PCL") != -1) or \
67          (data.find("LANGUAGE = PCL") != -1) or \
68          (data.find("LANGUAGE = Pcl") != -1))) :
69        return 1
70    else :   
71        return 0
72   
73def pcl(infile) :   
74    """Count pages in a PostScript document."""
75    #
76    # Algorithm from pclcount
77    # (c) 2003, by Eduardo Gielamo Oliveira & Rodolfo Broco Manin
78    # published under the terms of the GNU General Public Licence v2.
79    #
80    # Backported from C to Python by Jerome Alet
81    #
82    tagsends = { "*b" : "W", "(s" : "W", ")s" : "W", "&p" : "X", "&l" : "X" } 
83    copies = 1
84    pagecount = 0
85    tag = None
86    while 1 :
87        char = infile.read(1)   # TODO : speed this up if possible
88        if not char :
89            break
90        if char == "\014" :   
91            pagecount += 1
92        elif char == "\033" :   
93            #
94            #     <ESC>*b###W -> Start of a binary block
95            #     <ESC>(s###W -> Start of a characters description block
96            #     <ESC>)s###W -> Start of a fonts description block
97            #     <ESC>&p###X -> Start of a non printable characters block
98            #     <ESC>&l###X -> Number of copies
99            #
100            tag = infile.read(2)
101            try :
102                tagend = tagsends[tag]
103            except KeyError :   
104                pass    # Unsupported PCL tag
105            else :   
106                # Now read the numeric argument
107                size = 0
108                while 1 :
109                    char = infile.read(1)
110                    if not char.isdigit() :
111                        break
112                    size = (size * 10) + int(char)   
113                if char == tagend :   
114                    if tag == "&l" :
115                        copies = size
116                    else :   
117                        # doing a read will prevent the seek
118                        # for unseekable streams.
119                        # we just ignore the block anyway.
120                        infile.read(size) 
121    return copies * pagecount       
122
123def smartpagecounter(filename) :
124    """Autodetects file format and returns number of pages."""
125    if filename == "-" :
126        # we must read from stdin
127        # but since stdin is not seekable, we have to use a temporary
128        # file instead.
129        infile = tempfile.TemporaryFile()
130        while 1 :
131            data = sys.stdin.read(256 * 1024) 
132            if not data :
133                break
134            infile.write(data)
135        infile.flush()   
136        infile.seek(0)
137    else :   
138        # normal file
139        infile = open(filename, "rb")
140       
141    # Try to detect file type by reading first block of datas   
142    firstblock = infile.read(1024)
143    infile.seek(0)
144    if ispostscript(firstblock) :
145        size = postscript(infile)
146    elif ispcl(firstblock) :   
147        size = pcl(infile)
148    else :   
149        sys.stderr.write("ERROR : Unknown file format for %s\n" % filename)
150        size = 0
151    infile.close()   
152    return size
153   
154if __name__ == "__main__" :   
155    if len(sys.argv) < 2 :
156        sys.argv.append("-")
157       
158    totalsize = 0   
159    for arg in sys.argv[1:] :
160        totalsize += smartpagecounter(arg)
161    print "%s" % totalsize
Note: See TracBrowser for help on using the browser.