Changeset 491 for pkpgcounter/trunk/pkpgpdls
- Timestamp:
- 11/20/07 00:04:09 (17 years ago)
- Location:
- pkpgcounter/trunk/pkpgpdls
- Files:
-
- 17 modified
Legend:
- Unmodified
- Added
- Removed
-
pkpgcounter/trunk/pkpgpdls/analyzer.py
r485 r491 54 54 self.options = options 55 55 self.filename = filename 56 self. infile = None56 self.workfile = None 57 57 self.mustclose = None 58 58 … … 82 82 try : 83 83 pdlhandler = self.detectPDLHandler() 84 (handle, filename) = tempfile.mkstemp(".tmp", "pkpgcounter") 85 os.close(handle) 86 try : 87 pdlhandler.convertToTiffMultiPage24NC(filename, self.options.resolution) 88 result = inkcoverage.getInkCoverage(filename, cspace) 89 finally : 90 try : 91 os.remove(filename) 92 except OSError : 93 sys.stderr.write("Problem when trying to remove temporary file %s\n" % filename) 84 pdlhandler.convertToTiffMultiPage24NC(self.filename, self.options.resolution) 85 result = inkcoverage.getInkCoverage(self.filename, cspace) 94 86 except pdlparser.PDLParserError, msg : 95 87 raise pdlparser.PDLParserError, "Unknown file format for %s (%s)" % (self.filename, msg) … … 100 92 def openFile(self) : 101 93 """Opens the job's data stream for reading.""" 102 self.mustclose = 0# by default we don't want to close the file when finished94 self.mustclose = False # by default we don't want to close the file when finished 103 95 if hasattr(self.filename, "read") and hasattr(self.filename, "seek") : 104 96 # filename is in fact a file-like object … … 109 101 else : 110 102 # normal file 111 self. infile = open(self.filename, "rbU")112 self.mustclose = 1103 self.workfile = open(self.filename, "rb") 104 self.mustclose = True 113 105 return 114 106 115 107 # Use a temporary file, always seekable contrary to standard input. 116 self.infile = tempfile.TemporaryFile(mode="w+b") # TODO : not opened in universal newline mode, Python 2.5 refuses. 117 while 1 : 108 self.workfile = tempfile.NamedTemporaryFile(mode="w+b") 109 self.filename = self.workfile.name 110 while True : 118 111 data = infile.read(pdlparser.MEGABYTE) 119 112 if not data : 120 113 break 121 self. infile.write(data)122 self. infile.flush()123 self. infile.seek(0)114 self.workfile.write(data) 115 self.workfile.flush() 116 self.workfile.seek(0) 124 117 125 118 def closeFile(self) : 126 """Closes the job's data stream if we can close it."""119 """Closes the job's data stream if we have to.""" 127 120 if self.mustclose : 128 self.infile.close() 129 else : 130 # if we don't have to close the file, then 131 # ensure the file pointer is reset to the 132 # start of the file in case the process wants 133 # to read the file again. 134 try : 135 self.infile.seek(0) 136 except IOError : 137 pass # probably stdin, which is not seekable 121 self.workfile.close() 138 122 139 123 def detectPDLHandler(self) : … … 142 126 Returns the correct PDL handler class or None if format is unknown 143 127 """ 144 # Try to detect file type by reading first and last blocks of datas 145 # Each parser can read them automatically, but here we do this only once. 146 self.infile.seek(0) 147 firstblock = self.infile.read(pdlparser.FIRSTBLOCKSIZE) 148 try : 149 self.infile.seek(-pdlparser.LASTBLOCKSIZE, 2) 150 lastblock = self.infile.read(pdlparser.LASTBLOCKSIZE) 151 except IOError : 152 lastblock = "" 153 self.infile.seek(0) 154 if not firstblock : 128 if not os.stat(self.filename).st_size : 155 129 raise pdlparser.PDLParserError, "input file %s is empty !" % str(self.filename) 156 else : 157 # IMPORTANT : the order is important below. FIXME. 158 for module in (postscript, \ 159 pclxl, \ 160 pdf, \ 161 qpdl, \ 162 spl1, \ 163 dvi, \ 164 tiff, \ 165 zjstream, \ 166 ooo, \ 167 hbp, \ 168 lidil, \ 169 pcl345, \ 170 escp2, \ 171 escpages03, \ 172 plain) : # IMPORTANT : don't move this one up ! 173 try : 174 return module.Parser(self.infile, self.options.debug, firstblock, lastblock) 175 except pdlparser.PDLParserError : 176 pass # try next parser 130 # IMPORTANT : the order is important below. FIXME. 131 for module in (postscript, \ 132 pclxl, \ 133 pdf, \ 134 qpdl, \ 135 spl1, \ 136 dvi, \ 137 tiff, \ 138 zjstream, \ 139 ooo, \ 140 hbp, \ 141 lidil, \ 142 pcl345, \ 143 escp2, \ 144 escpages03, \ 145 plain) : # IMPORTANT : don't move this one up ! 146 try : 147 return module.Parser(self.filename, self.options.debug) 148 except pdlparser.PDLParserError : 149 pass # try next parser 177 150 raise pdlparser.PDLParserError, "Analysis of first data block failed." 178 151 … … 254 227 sys.stderr.flush() 255 228 if not options.colorspace : 256 print "% s" % totalsize229 print "%i" % totalsize 257 230 else : 258 231 print "\n".join(lines) -
pkpgcounter/trunk/pkpgpdls/dvi.py
r489 r491 75 75 minfile.close() # reached EOF 76 76 return pagecount 77 78 if __name__ == "__main__" :79 pdlparser.test(Parser) -
pkpgcounter/trunk/pkpgpdls/escp2.py
r473 r491 74 74 else : 75 75 return int(pagecount1 / 2) 76 77 if __name__ == "__main__" :78 pdlparser.test(Parser) -
pkpgcounter/trunk/pkpgpdls/escpages03.py
r475 r491 93 93 minfile.close() 94 94 return pagecount 95 96 if __name__ == "__main__" :97 pdlparser.test(Parser) -
pkpgcounter/trunk/pkpgpdls/hbp.py
r489 r491 74 74 minfile.close() # reached EOF 75 75 return pagecount 76 77 if __name__ == "__main__" :78 pdlparser.test(Parser) -
pkpgcounter/trunk/pkpgpdls/lidil.py
r488 r491 29 29 """ 30 30 31 import sys32 import os33 import mmap34 31 import struct 35 32 36 33 import pdlparser 34 35 HEADERSIZE = 10 # LIDIL header is 10 bytes long 37 36 38 37 # Packet types taken from hplip-2.7.10/prnt/ldl.py … … 74 73 unpack = struct.unpack 75 74 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() 75 while True : 76 header = self.infile.read(HEADERSIZE) 77 if not header : 78 break 79 if (len(header) != HEADERSIZE) or (header[0] != "$") : 80 # Invalid header or no Frame Sync byte. 81 raise pdlparser.PDLParserError, "This file doesn't seem to be valid Hewlett-Packard LIDIL datas." 82 try : 83 (framesync, 84 cmdlength, 85 dummy, 86 packettype, 87 commandnumber, 88 referencenumber, 89 datalength) = unpack(">BHBBBHH", header) 90 except struct.error : 91 raise pdlparser.PDLParserError, "This file doesn't seem to be valid Hewlett-Packard LIDIL datas." 92 if packettype == PACKET_TYPE_COMMAND : 93 if commandnumber == LDL_LOAD_PAGE : 94 loadpage += 1 95 elif commandnumber == LDL_EJECT_PAGE : 96 ejectpage += 1 97 self.infile.seek(cmdlength + datalength - len(header), 1) # relative seek 104 98 105 99 # Number of page eject commands should be sufficient, … … 110 104 self.logdebug("Load : %i Eject : %i" % (loadpage, ejectpage)) 111 105 return max(loadpage, ejectpage) 112 113 if __name__ == "__main__" :114 pdlparser.test(Parser) -
pkpgcounter/trunk/pkpgpdls/ooo.py
r463 r491 62 62 raise pdlparser.PDLParserError, "OpenOffice.org's spreadsheet documents are not yet supported." 63 63 return pagecount 64 65 if __name__ == "__main__" :66 pdlparser.test(Parser) -
pkpgcounter/trunk/pkpgpdls/pcl345.py
r478 r491 571 571 572 572 return self.pagecount 573 574 if __name__ == "__main__" :575 pdlparser.test(Parser) -
pkpgcounter/trunk/pkpgpdls/pclxl.py
r479 r491 700 700 colormode)) 701 701 return self.pagecount 702 703 if __name__ == "__main__" :704 pdlparser.test(Parser) -
pkpgcounter/trunk/pkpgpdls/pdf.py
r463 r491 23 23 """This modules implements a page counter for PDF documents.""" 24 24 25 import sys26 25 import re 27 26 … … 34 33 self.major = major 35 34 self.minor = minor 35 self.majori = int(major) 36 self.minori = int(minor) 36 37 self.description = description 37 38 self.comments = [] … … 43 44 """A parser for PDF documents.""" 44 45 totiffcommands = [ 'gs -sDEVICE=tiff24nc -dPARANOIDSAFER -dNOPAUSE -dBATCH -dQUIET -r%(dpi)i -sOutputFile="%(fname)s" -' ] 46 openmode = "rU" 45 47 def isValid(self) : 46 48 """Returns True if data is PDF, else False.""" … … 62 64 objre = re.compile(r"\s?(\d+)\s+(\d+)\s+obj[<\s/]?") 63 65 for line in self.infile : 64 line = line.strip() 66 line = line.strip() 65 67 if line.startswith("% ") : 66 68 if inobject : … … 72 74 result = objre.search(line) 73 75 if result is not None : 74 (major, minor) = [int(num) for num in line[result.start():result.end()].split()[:2]]76 (major, minor) = line[result.start():result.end()].split()[:2] 75 77 obj = PDFObject(major, minor, lastcomment) 76 78 obj.content.append(line[result.end():]) … … 86 88 # if we want the first one, just use > instead of >= 87 89 oldobject = objects.setdefault(major, obj) 88 if minor >= oldobject.minor:90 if int(minor) >= oldobject.minori : 89 91 objects[major] = obj 92 # self.logdebug("Object(%i, %i) overwritten with Object(%i, %i)" % (oldobject.majori, oldobject.minori, obj.majori, obj.minori)) 93 # self.logdebug("Object(%i, %i)" % (obj.majori, obj.minori)) 90 94 inobject = 0 91 95 else : … … 94 98 95 99 # Now we check each PDF object we've just created. 96 # colorregexp = re.compile(r"(/ColorSpace) ?(/DeviceRGB|/DeviceCMYK)[/ \t\r\n]", re.I)97 100 newpageregexp = re.compile(r"(/Type)\s?(/Page)[/>\s]", re.I) 98 101 pagecount = 0 … … 103 106 pagecount += count 104 107 return pagecount 105 106 if __name__ == "__main__" :107 pdlparser.test(Parser) -
pkpgcounter/trunk/pkpgpdls/pdlparser.py
r463 r491 42 42 """Generic PDL parser.""" 43 43 totiffcommands = None # Default command to convert to TIFF 44 def __init__(self, infile, debug=0, firstblock=None, lastblock=None) : 44 openmode = "rb" # Default file opening mode 45 def __init__(self, filename, debug=0) : 45 46 """Initialize the generic parser.""" 46 self. infile = infile47 self.filename = filename 47 48 self.debug = debug 48 if firstblock is None : 49 self.infile.seek(0) 50 firstblock = self.infile.read(FIRSTBLOCKSIZE) 51 try : 52 self.infile.seek(-LASTBLOCKSIZE, 2) 53 lastblock = self.infile.read(LASTBLOCKSIZE) 54 except IOError : 55 lastblock = "" 56 self.infile.seek(0) 57 self.firstblock = firstblock 58 self.lastblock = lastblock 49 self.infile = None 50 (self.firstblock, self.lastblock) = self.readBlocks() 51 self.infile = open(self.filename, self.openmode) 59 52 if not self.isValid() : 60 53 raise PDLParserError, "Invalid file format !" … … 68 61 # parsing will greatly benefit from this. 69 62 psyco.bind(self.getJobSize) 63 64 def __del__(self) : 65 """Ensures the input file gets closed.""" 66 if self.infile : 67 self.infile.close() 68 69 def readBlocks(self) : 70 """Reads first and last block of the input file.""" 71 infile = open(self.filename, "rb") 72 try : 73 firstblock = infile.read(FIRSTBLOCKSIZE) 74 try : 75 infile.seek(-LASTBLOCKSIZE, 2) 76 lastblock = infile.read(LASTBLOCKSIZE) 77 except IOError : 78 lastblock = "" 79 finally : 80 infile.close() 81 return (firstblock, lastblock) 70 82 71 83 def logdebug(self, message) : … … 87 99 """ 88 100 if self.totiffcommands : 89 for totiffcommand in self.totiffcommands : 90 self.infile.seek(0) 91 error = False 92 commandline = totiffcommand % locals() 93 child = popen2.Popen4(commandline) 94 try : 101 infile = open(self.filename, "rb") 102 try : 103 for totiffcommand in self.totiffcommands : 104 infile.seek(0) 105 error = False 106 commandline = totiffcommand % locals() 107 child = popen2.Popen4(commandline) 95 108 try : 96 data = self.infile.read(MEGABYTE) 97 while data : 98 child.tochild.write(data) 99 child.tochild.flush() 100 data = self.infile.read(MEGABYTE) 101 except (IOError, OSError) : 109 try : 110 data = infile.read(MEGABYTE) 111 while data : 112 child.tochild.write(data) 113 child.tochild.flush() 114 data = infile.read(MEGABYTE) 115 except (IOError, OSError) : 116 error = True 117 finally : 118 child.tochild.close() 119 dummy = child.fromchild.read() 120 child.fromchild.close() 121 122 try : 123 status = child.wait() 124 except OSError : 102 125 error = True 103 finally : 104 child.tochild.close() 105 dummy = child.fromchild.read() 106 child.fromchild.close() 107 108 try : 109 status = child.wait() 110 except OSError : 111 error = True 112 else : 113 if os.WIFEXITED(status) : 114 if os.WEXITSTATUS(status) : 126 else : 127 if os.WIFEXITED(status) : 128 if os.WEXITSTATUS(status) : 129 error = True 130 else : 115 131 error = True 132 133 if not os.path.exists(fname) : 134 error = True 135 elif not os.stat(fname).st_size : 136 error = True 116 137 else : 117 error = True 118 119 if not os.path.exists(fname) : 120 error = True 121 elif not os.stat(fname).st_size : 122 error = True 123 else : 124 break # Conversion worked fine it seems. 125 self.logdebug("Command failed : %s" % repr(commandline)) 138 break # Conversion worked fine it seems. 139 self.logdebug("Command failed : %s" % repr(commandline)) 140 finally : 141 infile.close() 126 142 if error : 127 143 raise PDLParserError, "Problem during conversion to TIFF." 128 144 else : 129 145 raise PDLParserError, "Impossible to compute ink coverage for this file format." 130 131 def test(parserclass) :132 """Test function."""133 if (len(sys.argv) < 2) or ((not sys.stdin.isatty()) and ("-" not in sys.argv[1:])) :134 sys.argv.append("-")135 totalsize = 0136 for arg in sys.argv[1:] :137 if arg == "-" :138 infile = sys.stdin139 mustclose = 0140 else :141 infile = open(arg, "rbU")142 mustclose = 1143 try :144 parser = parserclass(infile, debug=1)145 totalsize += parser.getJobSize()146 except PDLParserError, msg :147 sys.stderr.write("ERROR: %s\n" % msg)148 sys.stderr.flush()149 if mustclose :150 infile.close()151 print "%s" % totalsize152 -
pkpgcounter/trunk/pkpgpdls/plain.py
r463 r491 23 23 """This modules implements a page counter for plain text documents.""" 24 24 25 import sys26 import os27 28 25 import pdlparser 29 26 import version 30 31 27 32 28 class Parser(pdlparser.PDLParser) : … … 35 31 'a2ps --borders 0 --quiet --portrait --no-header --columns 1 --output - | gs -sDEVICE=tiff24nc -dPARANOIDSAFER -dNOPAUSE -dBATCH -dQUIET -r%(dpi)i -sOutputFile="%(fname)s" -', 36 32 ] 33 openmode = "rU" 37 34 def isValid(self) : 38 35 """Returns True if data is plain text, else False. … … 57 54 linecount = 0 58 55 for line in self.infile : 59 if line.endswith("\n") or line.endswith("\r"):56 if line.endswith("\n") : 60 57 linecount += 1 61 58 if (linecount > pagesize) : … … 70 67 raise pdlparser.PDLParserError, "Unsupported file format. Please send the file to %s" % version.__authoremail__ 71 68 return pagecount + 1 # NB : empty files are catched in isValid() 72 73 if __name__ == "__main__" :74 pdlparser.test(Parser) -
pkpgcounter/trunk/pkpgpdls/postscript.py
r463 r491 34 34 """A parser for PostScript documents.""" 35 35 totiffcommands = [ 'gs -sDEVICE=tiff24nc -dPARANOIDSAFER -dNOPAUSE -dBATCH -dQUIET -r%(dpi)i -sOutputFile="%(fname)s" -' ] 36 openmode = "rU" 36 37 def isValid(self) : 37 38 """Returns True if data is PostScript, else False.""" … … 52 53 """Get the count through GhostScript, useful for non-DSC compliant PS files.""" 53 54 self.logdebug("Internal parser sucks, using GhostScript instead...") 54 self.infile.seek(0)55 55 command = 'gs -sDEVICE=bbox -dPARANOIDSAFER -dNOPAUSE -dBATCH -dQUIET - 2>&1 | grep -c "%%HiResBoundingBox:" 2>/dev/null' 56 child = popen2.Popen4(command) 56 pagecount = 0 57 # we need to reopen the input file in binary mode again, just in case 58 # otherwise we might break the original file's contents. 59 infile = open(self.filename, "rb") 57 60 try : 58 data = self.infile.read(pdlparser.MEGABYTE) 59 while data : 60 child.tochild.write(data) 61 data = self.infile.read(pdlparser.MEGABYTE) 62 child.tochild.flush() 63 child.tochild.close() 64 except (IOError, OSError), msg : 65 raise pdlparser.PDLParserError, "Problem during analysis of Binary PostScript document : %s" % msg 61 child = popen2.Popen4(command) 62 try : 63 data = infile.read(pdlparser.MEGABYTE) 64 while data : 65 child.tochild.write(data) 66 data = infile.read(pdlparser.MEGABYTE) 67 child.tochild.flush() 68 child.tochild.close() 69 except (IOError, OSError), msg : 70 raise pdlparser.PDLParserError, "Problem during analysis of Binary PostScript document : %s" % msg 71 72 pagecount = 0 73 try : 74 pagecount = int(child.fromchild.readline().strip()) 75 except (IOError, OSError, AttributeError, ValueError), msg : 76 raise pdlparser.PDLParserError, "Problem during analysis of Binary PostScript document : %s" % msg 77 child.fromchild.close() 66 78 67 pagecount = 0 68 try : 69 pagecount = int(child.fromchild.readline().strip()) 70 except (IOError, OSError, AttributeError, ValueError), msg : 71 raise pdlparser.PDLParserError, "Problem during analysis of Binary PostScript document : %s" % msg 72 child.fromchild.close() 73 74 try : 75 child.wait() 76 except OSError, msg : 77 raise pdlparser.PDLParserError, "Problem during analysis of Binary PostScript document : %s" % msg 79 try : 80 child.wait() 81 except OSError, msg : 82 raise pdlparser.PDLParserError, "Problem during analysis of Binary PostScript document : %s" % msg 83 finally : 84 infile.close() 78 85 self.logdebug("GhostScript said : %s pages" % pagecount) 79 86 return pagecount * self.copies … … 81 88 def natively(self) : 82 89 """Count pages in a DSC compliant PostScript document.""" 83 self.infile.seek(0)84 90 pagecount = 0 85 91 self.pages = { 0 : { "copies" : 1 } } … … 90 96 acrobatmarker = 0 91 97 pagescomment = None 92 for line in self.infile : 98 for line in self.infile : 99 line = line.strip() 93 100 if (not prescribe) and line.startswith(r"%%BeginResource: procset pdf") \ 94 101 and not acrobatmarker : … … 121 128 elif line.startswith(r"%%Requirements: numcopies(") : 122 129 try : 123 number = int(line.s trip().split('(')[1].split(')')[0])130 number = int(line.split('(')[1].split(')')[0]) 124 131 except : 125 132 pass … … 130 137 # handle # of copies set by some Windows printer driver 131 138 try : 132 number = int(line.s trip().split()[2])139 number = int(line.split()[2]) 133 140 except : 134 141 pass … … 139 146 # handle # of copies set by mozilla/kprinter 140 147 try : 141 number = int(line.s trip().split()[4])148 number = int(line.split()[4]) 142 149 except : 143 150 pass … … 148 155 # handle # of copies set by firefox/kprinter/cups (alternate syntax) 149 156 try : 150 number = int(line.s trip().split()[6])157 number = int(line.split()[6]) 151 158 except : 152 159 pass … … 156 163 elif line.startswith("/languagelevel where{pop languagelevel}{1}ifelse 2 ge{1 dict dup/NumCopies") : 157 164 try : 158 number = int(previousline .strip()[2:])165 number = int(previousline[2:]) 159 166 except : 160 167 pass … … 164 171 elif line.startswith("/#copies ") : 165 172 try : 166 number = int(line.s trip().split()[1])173 number = int(line.split()[1]) 167 174 except : 168 175 pass … … 172 179 elif line.startswith(r"%RBINumCopies: ") : 173 180 try : 174 number = int(line.s trip().split()[1])181 number = int(line.split()[1]) 175 182 except : 176 183 pass … … 207 214 self.logdebug(msg) 208 215 return max(nbpages, newnbpages) 209 210 if __name__ == "__main__" :211 pdlparser.test(Parser) -
pkpgcounter/trunk/pkpgpdls/qpdl.py
r463 r491 292 292 duplexmode)) 293 293 return self.pagecount 294 295 if __name__ == "__main__" :296 pdlparser.test(Parser) -
pkpgcounter/trunk/pkpgpdls/spl1.py
r487 r491 125 125 minfile.close() 126 126 return self.pagecount 127 128 if __name__ == "__main__" :129 pdlparser.test(Parser) -
pkpgcounter/trunk/pkpgpdls/tiff.py
r489 r491 79 79 minfile.close() 80 80 return pagecount 81 82 if __name__ == "__main__" :83 pdlparser.test(Parser) -
pkpgcounter/trunk/pkpgpdls/zjstream.py
r463 r491 23 23 """This modules implements a page counter for ZjStream documents.""" 24 24 25 import sys 26 import os 27 import mmap 28 from struct import unpack 25 import struct 29 26 30 27 import pdlparser … … 36 33 if self.firstblock[:4] == "ZJZJ" : 37 34 self.logdebug("DEBUG: Input file is in the Zenographics ZjStream (little endian) format.") 38 self.littleEndian() 39 return True 35 return self.littleEndian() 40 36 elif self.firstblock[:4] == "JZJZ" : 41 37 self.logdebug("DEBUG: Input file is in the Zenographics ZjStream (big endian) format.") 42 self.bigEndian() 43 return True 38 return self.bigEndian() 44 39 else : 45 40 return False … … 47 42 def littleEndian(self) : 48 43 """Toggles to little endianness.""" 49 self.unpackType = { 1 : "B", 2 : "<H", 4 : "<I" } 50 self.unpackShort = self.unpackType[2] 51 self.unpackLong = self.unpackType[4] 52 return 0 44 self.unpackHeader = "<IIIHH" 45 return True 53 46 54 47 def bigEndian(self) : 55 48 """Toggles to big endianness.""" 56 self.unpackType = { 1 : "B", 2 : ">H", 4 : ">I" } 57 self.unpackShort = self.unpackType[2] 58 self.unpackLong = self.unpackType[4] 59 return 0 49 self.unpackHeader = ">IIIHH" 50 return True 60 51 61 52 def getJobSize(self) : 62 53 """Computes the number of pages in a ZjStream document.""" 63 infileno = self.infile.fileno() 64 minfile = mmap.mmap(infileno, os.fstat(infileno)[6], prot=mmap.PROT_READ, flags=mmap.MAP_SHARED) 65 pos = 4 54 unpack = struct.unpack 55 self.infile.seek(4, 0) # Skip ZJZJ/JZJZ header 66 56 startpagecount = endpagecount = 0 67 try : 68 try : 69 while 1 : 70 header = minfile[pos:pos+16] 71 if len(header) != 16 : 72 break 73 totalChunkSize = unpack(self.unpackLong, header[:4])[0] 74 chunkType = unpack(self.unpackLong, header[4:8])[0] 75 numberOfItems = unpack(self.unpackLong, header[8:12])[0] 76 reserved = unpack(self.unpackShort, header[12:14])[0] 77 signature = unpack(self.unpackShort, header[14:])[0] 78 pos += totalChunkSize 79 if chunkType == 0 : 80 self.logdebug("startDoc") 81 elif chunkType == 1 : 82 self.logdebug("endDoc") 83 elif chunkType == 2 : 84 self.logdebug("startPage") 85 startpagecount += 1 86 elif chunkType == 3 : 87 self.logdebug("endPage") 88 endpagecount += 1 89 90 #self.logdebug("Chunk size : %s" % totalChunkSize) 91 #self.logdebug("Chunk type : 0x%08x" % chunkType) 92 #self.logdebug("# items : %s" % numberOfItems) 93 #self.logdebug("reserved : 0x%04x" % reserved) 94 #self.logdebug("signature : 0x%04x" % signature) 95 #self.logdebug("\n") 96 except IndexError : # EOF ? 97 pass 98 finally : 99 minfile.close() 57 while True : 58 header = self.infile.read(16) 59 if not header : 60 break 61 try : 62 (totalChunkSize, 63 chunkType, 64 numberOfItems, 65 reserved, 66 signature) = unpack(self.unpackHeader, header) 67 except struct.error : 68 raise pdlparser.PDLParserError, "This file doesn't seem to be valid ZjStream datas." 69 self.infile.seek(totalChunkSize - len(header), 1) 70 if chunkType == 2 : 71 #self.logdebug("startPage") 72 startpagecount += 1 73 elif chunkType == 3 : 74 #self.logdebug("endPage") 75 endpagecount += 1 76 #elif chunkType == 0 : 77 # self.logdebug("startDoc") 78 #elif chunkType == 1 : 79 # self.logdebug("endDoc") 80 81 #self.logdebug("Chunk size : %s" % totalChunkSize) 82 #self.logdebug("Chunk type : 0x%08x" % chunkType) 83 #self.logdebug("# items : %s" % numberOfItems) 84 #self.logdebug("reserved : 0x%04x" % reserved) 85 #self.logdebug("signature : 0x%04x" % signature) 86 #self.logdebug("\n") 100 87 101 if startpagecount != endpagecount : 102 sys.stderr.write("ERROR: Incorrect ZjStream datas.\n") 88 # Number of endpage commands should be sufficient, 89 # but we never know : someone could try to cheat the printer 90 # by starting a page but not ending it, and ejecting it manually 91 # later on. Not sure if the printers would support this, but 92 # taking the max value works around the problem in any case. 93 self.logdebug("StartPage : %i EndPage : %i" % (startpagecount, endpagecount)) 103 94 return max(startpagecount, endpagecount) 104 105 if __name__ == "__main__" :106 pdlparser.test(Parser)