For
pycups method, cups.writeRequestData, there is a
bug that will corrupt binary data when streamed
through this method.
This
python code will expose the problem:
import
cups
x = None
conn = cups.Connection()
id = conn.createJob('printer', 'blah', {
'document-format': cups.CUPS_FORMAT_AUTO })
conn.startDocument('printer', id, 'asdfasd',
cups.CUPS_FORMAT_AUTO, 1)
with open('test.pdf', 'rb') as f:
while True:
x = f.read(1024)
if len(x):
conn.writeRequestData(x, len(x))
else:
break
conn.finishDocument('printer')
The
printer will print out a sheet with the text:
PDF
Error 10: PostScript: Error: IOERROR
Assert
FaileD: rc == curStrLen
If
you take the print queue down and print the same
file with lpr -P printer, the md5sums in
/var/spool/cups are different. Each lpr command
produces a queued file with the same hash as the
original file. Each file printed through the
API will have a different sum each time.
The issue is caused by this line in
the code:
buffer = strdup(PyBytes_AsString
(buffer_obj));
The strdup detects a null in the
Python byte array and ends the copy. This
causes a buffer overrun when "status =
cupsWriteRequestData(self->http, buffer,
length);" is called. This is because the buffer
might only have 120 bytes in it, and the length
is equal to, says, 8192.
I switched over to memcpy, and
malloc'd a separate buffer. I choose memcpy as
this method is not overrun safe. The caller
must mind his or her own buffer size. The
method now works with jpgs, pdfs, and regular
text files.
Feel free to make my code better as my
C is a bit rusty.
Doug