quick-n-dirty HTTP-based remote printing

Replies:

  • None.

Parents:

  • None.
This is a multi-part message in MIME format.
--------------BA1F86867B2F9EF354896AAE
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

I don't know why remote printing has to be so hard...
I haven't found a simple, reliable remote printing
setup under debian linux for a couple years now. I
just want to print expense reports and such from my laptop
to my desktop machine. That shouldn't be rocket-science,
should it? (OK, so I want some Windows interoperability too,
but that's for another day...)

So I scratched the itch for an hour or so, and sure
enough: HTTP POST with file upload works just fine for submitting
print jobs.  Attached find my client and server scripts with
references and such...

The client is a one-liner on top of curl:

 curl --silent --form printer=jobie --form dataPS=@- \
http://192.168.1.1/cgi-bin/print0108

It works great from the Netscape print dialog.

And the server CGI is hardly more than a one-liner on top of pdq:

posix.popen("pdq -d %s" % (printer,), "w").write(jobData)

plus enough error-handling to debug it to the point where it works.

I think I've gotten samba-based remote printing before,
but it seems to fall apart whenever I change my configuration,
and getting it working again involves more hunting thru
spellbooks than seems worthwhile. Even when I have found
the relevant spells, I have never understood how/why they work
well enough to trouble-shoot.

Same for lpd.

I haven't tried CUPS. It looks big and hairy.

The Internet Printing Protocol is HTTP-based; I'd like to think
that with a little tweaking,
my client script should work with IPP servers, and that
the Windows support for IPP should interoperate with my
little server deely. Let's see if they've followed the
basic design I went with...

Surfing in/around
 http://www.pwg.org/ipp/
...

  "The protocol is heavily influenced by the printing model introduced
  in the Document Printing Application (DPA) [ISO10175] standard."
-- http://ietf.org/rfc/rfc2568.txt?number=2568

Ugh. I worked with that standard in a previous life.
I hope never to return to that nightmare.

Ugh. the implementors guide is 64 pages, and I don't see
a "hello world" example anywhere in sight.
http://ietf.org/rfc/rfc2639.txt?number=2639

Sigh. Oh well... I'm happily printing with my little scripts...

Next steps:

 -- put an HTML form interface on the server so I can use it
 from a box that doesn't have curl (e.g. Windows)

 -- add support for PDF (maybe it's already there), SVG, PNG,
plain text, maybe XHTML (via html2ps)

 -- get job data by reference rather than by value (maybe)

--
Dan Connolly, W3C http://www.w3.org/People/Connolly/
--------------BA1F86867B2F9EF354896AAE
Content-Type: text/plain; charset=us-ascii;
name="print-jobie"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="print-jobie"

#!/bin/sh
#
# USAGE:
#  print-jobie <foo.ps
#
# or use in the Netscape print dialog.
#
# $Id$
#
# by Dan Connolly http://www.w3.org/People/Connolly/
# copyright (c) 2001 W3C (MIT, INRIA, Keio).
# released under an Open Source license.
# see http://www.w3.org/Consortium/Legal/copyright-software-19980720
#
# REFERENCES
# cURL - a client that groks URLs
# http://curl.haxx.se/
#
# Package: curl 6.0-1.1.1
# Get a file from an FTP, GOPHER, or HTTP server. (no ssl)
# http://packages.debian.org/stable/web/curl.html

curl --silent --form printer=jobie --form dataPS=@- http://192.168.1.1/cgi-bin/print0108

# $Log$

--------------BA1F86867B2F9EF354896AAE
Content-Type: text/plain; charset=us-ascii;
name="print0108"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="print0108"

#!/usr/bin/python
#
# USAGE
#  per CGI conventions (@@cite), using file-upload (multipart/form-data).
#  params are:
#   printer -- printer name from pdq config
#   dataPS -- postscript data
#
# SECURITY ISSUES
#   Use of this script MAKES YOUR PRINTER AVAILABLE TO ANYBODY ON THE PLANET.
#   It might even run malicious postscript code from black hats.
#   Use at your own risk. You have been warned.
#   Bonus points for anybody who upgrades this thing to use
#   Digest Authentication (@@cite) and sends me a patch.
#
# by Dan Connolly http://www.w3.org/People/Connolly/
# copyright (c) 2001 W3C (MIT, INRIA, Keio).
# Share and Enjoy. For Open Source license details, see
# http://www.w3.org/Consortium/Legal/copyright-software-19980720
#
#
# REFERENCES
# pdq
#   http://pdq.sourceforge.net/
#   http://packages.debian.org/testing/utils/pdq.html
rcsid = "$Id: print0108,v 1.3 2001/08/13 04:23:50 connolly Exp $"

import cgi
import os, posix

BadRequest='400'
ServiceProblem='500'

def printJob():
   reqFields = cgi.FieldStorage()

   try:
printer = reqFields['printer'].value
   except:
raise BadRequest, "cannot find printer name from request" + `reqFields.keys()`

   try:
jobData = reqFields['dataPS'].value
   except:
raise BadRequest, "cannot find job data from request" + `reqFields.keys()`

#    if not os.path.exists("%s/.printrc" % (os.environ['HOME'],)):
# raise ServiceProblem, "no .printrc in %s" % (os.environ['HOME'],)

   if printer == 'jobie':
cmd = "pdq -d %s" % (printer,)
try:
   pdqPipe = posix.popen(cmd, "w")
except:
   raise ServiceProblem, "cannot open pipe to command: %s" % (cmd,)

try:
   pdqPipe.write(jobData)
   pdqPipe.close()
except:
   raise ServiceProblem, "error writing to pipe to command: %s" % (cmd,)

return (len(jobData), printer)


   else:
raise BadRequest, "no such printer: %s." % (printer,)


if __name__ == '__main__':
   try:
bytes, printerName = printJob()
   except BadRequest, detail:
print "Status: 404 Bad request"
print "Content-Type: text/plain"
print
print detail
   except ServiceProblem, detail:
print "Status: 500 Service problem"
print "Content-Type: text/plain"
print
print detail

   print "Status: 200 OK"
   print "Content-Type: text/plain"
   print
   print "sent %d bytes to printer %s." % (bytes, printerName)
   print "Thanks for using %s." % (rcsid)

--------------BA1F86867B2F9EF354896AAE--

HURL: fogo mailing list archives, maintained by Gerald Oskoboiny