mirror of
https://github.com/NaitLee/Cat-Printer.git
synced 2025-05-20 09:10:08 -07:00
Very early IPP support, works with cups on unix
This commit is contained in:
parent
3123548ab5
commit
64d1c3528b
93
server.py
93
server.py
@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
from http.server import HTTPServer, BaseHTTPRequestHandler
|
from http.server import HTTPServer, BaseHTTPRequestHandler
|
||||||
import socketserver, threading, urllib, os, asyncio
|
import socketserver, threading, urllib, os, asyncio, tempfile, platform
|
||||||
from printer import PrinterDriver
|
from printer import PrinterDriver
|
||||||
import bleak
|
import bleak
|
||||||
|
|
||||||
@ -76,6 +76,10 @@ class PrinterServer(BaseHTTPRequestHandler):
|
|||||||
self.wfile.write(b'Not Found')
|
self.wfile.write(b'Not Found')
|
||||||
return
|
return
|
||||||
def do_POST(self):
|
def do_POST(self):
|
||||||
|
if self.headers.get('Content-Type', '') == 'application/ipp':
|
||||||
|
# https://datatracker.ietf.org/doc/html/rfc8010
|
||||||
|
self.handle_ipp()
|
||||||
|
return
|
||||||
path = urllib.parse.unquote(self.path)
|
path = urllib.parse.unquote(self.path)
|
||||||
v = urlvar(path)
|
v = urlvar(path)
|
||||||
path = path.split('?')[0]
|
path = path.split('?')[0]
|
||||||
@ -90,7 +94,6 @@ class PrinterServer(BaseHTTPRequestHandler):
|
|||||||
try:
|
try:
|
||||||
content_length = int(self.headers.get('Content-Length'))
|
content_length = int(self.headers.get('Content-Length'))
|
||||||
data = self.rfile.read(content_length)
|
data = self.rfile.read(content_length)
|
||||||
assert content_length == len(data), 'Post data not fully read'
|
|
||||||
asyncio.run(self.driver.print_data(data, v['address']))
|
asyncio.run(self.driver.print_data(data, v['address']))
|
||||||
self.send_response(200)
|
self.send_response(200)
|
||||||
self.send_header('Content-Type', 'text/plain')
|
self.send_header('Content-Type', 'text/plain')
|
||||||
@ -106,6 +109,92 @@ class PrinterServer(BaseHTTPRequestHandler):
|
|||||||
self.send_header('Content-Type', 'text/plain')
|
self.send_header('Content-Type', 'text/plain')
|
||||||
self.end_headers()
|
self.end_headers()
|
||||||
self.wfile.write(b'Bad Request')
|
self.wfile.write(b'Bad Request')
|
||||||
|
def handle_ipp(self):
|
||||||
|
path = urllib.parse.unquote(self.path)
|
||||||
|
printer_name = path[1:]
|
||||||
|
data = self.rfile.read(int(self.headers.get('Content-Length', 0)))
|
||||||
|
# len_data = len(data)
|
||||||
|
# ipp_version_number = data[0:2]
|
||||||
|
# ipp_operation_id = data[2:4]
|
||||||
|
# ipp_request_id = data[4:8]
|
||||||
|
ipp_operation_attributes_tag = data[8]
|
||||||
|
attributes = {}
|
||||||
|
data_to_print = b''
|
||||||
|
# b'\x01'[0] == int(1)
|
||||||
|
if ipp_operation_attributes_tag == b'\x01'[0]:
|
||||||
|
pointer = 9
|
||||||
|
next_name_length_at = 10
|
||||||
|
next_value_length_at = 10
|
||||||
|
name = b''
|
||||||
|
value = b''
|
||||||
|
while data[pointer] != b'\x03'[0]:
|
||||||
|
tag = data[pointer:pointer + 1]
|
||||||
|
pointer += 1
|
||||||
|
if tag[0] < 0x10: # delimiter-tag
|
||||||
|
continue
|
||||||
|
next_name_length_at = pointer + data[pointer] * 0x0100 + data[pointer + 1] + 2
|
||||||
|
pointer += 2
|
||||||
|
while pointer < next_name_length_at:
|
||||||
|
name = name + data[pointer:pointer + 1]
|
||||||
|
pointer += 1
|
||||||
|
next_value_length_at = pointer + data[pointer] * 0x0100 + data[pointer + 1] + 2
|
||||||
|
pointer += 2
|
||||||
|
while pointer < next_value_length_at:
|
||||||
|
value = value + data[pointer:pointer + 1]
|
||||||
|
pointer += 1
|
||||||
|
attributes[name] = (tag, value)
|
||||||
|
name = b''
|
||||||
|
value = b''
|
||||||
|
pointer += 1
|
||||||
|
data_to_print = data[pointer:]
|
||||||
|
if data_to_print == b'':
|
||||||
|
self.send_response(200)
|
||||||
|
self.send_header('Content-Type', 'application/ipp')
|
||||||
|
self.end_headers()
|
||||||
|
self.wfile.write(
|
||||||
|
b'\x01\x01\x00\x00\x00\x00\x00\x01\x01\x03'
|
||||||
|
)
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
devices = asyncio.run(bleak.BleakScanner.discover())
|
||||||
|
target_device = ''
|
||||||
|
for i in devices:
|
||||||
|
if i.name == printer_name:
|
||||||
|
target_device = i.address
|
||||||
|
if target_device != '':
|
||||||
|
platform_system = platform.system()
|
||||||
|
temp_dir = tempfile.mkdtemp()
|
||||||
|
temp_file_ps = os.path.join(temp_dir, 'temp.ps')
|
||||||
|
temp_file_pbm = os.path.join(temp_dir, 'temp.pbm')
|
||||||
|
f = open(temp_file_ps, 'wb')
|
||||||
|
f.write(data_to_print)
|
||||||
|
f.close()
|
||||||
|
# https://ghostscript.com/doc/9.54.0/Use.htm#Output_device
|
||||||
|
ghostscript_exe = 'gs'
|
||||||
|
if platform_system == 'Windows':
|
||||||
|
ghostscript_exe = 'gswin32c.exe'
|
||||||
|
elif platform_system == 'Linux':
|
||||||
|
ghostscript_exe = 'gs'
|
||||||
|
elif platform_system == 'OS/2':
|
||||||
|
ghostscript_exe = 'gsos2'
|
||||||
|
return_code = os.system('%s -q -sDEVICE=pbmraw -dNOPAUSE -dBATCH -dSAFER -dFIXEDMEDIA -g384x543 -r46.4441219158x46.4441219158 -dFitPage -sOutputFile="%s" "%s"' % (ghostscript_exe, temp_file_pbm, temp_file_ps))
|
||||||
|
if return_code == 0:
|
||||||
|
asyncio.run(self.driver.print_file(temp_file_pbm, target_device))
|
||||||
|
else:
|
||||||
|
raise Exception('Error on invoking Ghostscript')
|
||||||
|
# print(data_to_print)
|
||||||
|
self.send_response(200)
|
||||||
|
self.send_header('Content-Type', 'application/ipp')
|
||||||
|
self.end_headers()
|
||||||
|
self.wfile.write(
|
||||||
|
b'\x01\x01\x00\x00\x00\x00\x00\x01\x01\x03'
|
||||||
|
)
|
||||||
|
except Exception as _:
|
||||||
|
self.send_response(500)
|
||||||
|
self.send_header('Content-Type', 'application/ipp')
|
||||||
|
self.end_headers()
|
||||||
|
self.wfile.write(b'')
|
||||||
|
|
||||||
|
|
||||||
class ThreadedHTTPServer(socketserver.ThreadingMixIn, HTTPServer):
|
class ThreadedHTTPServer(socketserver.ThreadingMixIn, HTTPServer):
|
||||||
""" Handle requests in a separate thread. """
|
""" Handle requests in a separate thread. """
|
||||||
|
Loading…
x
Reference in New Issue
Block a user