This file is indexed.

/usr/lib/cups/backend/xpraforwarder is in xpra 0.15.8+dfsg-1.

This file is owned by root:root, with mode 0o755.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# xpraforwarder - A CUPS backend written in Python.
# Forwards the print job via xpra.
#
# It is based on pdf2email by Georde Notaras.
#
# Copyright (c) George Notaras <George [D.O.T.] Notaras [A.T.] gmail [D.O.T.] com>
# Copyright (C) 2014, 2015 Antoine Martin <antoine@devloop.org.uk>
#
# License: GPLv2
#
# This program is released with absolutely no warranty, expressed or implied,
# and absolutely no support.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the:
#
# Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston,
# MA 02111-1307  USA
#


import sys, os, syslog
import subprocess, traceback
import urlparse

__version__ = "0.15.0"

#Writes a syslog entry (msg) at the default facility:
def debug(msg):
	syslog.syslog(syslog.LOG_DEBUG, msg)

def info(msg):
	syslog.syslog(syslog.LOG_INFO, msg)

def err(msg):
	syslog.syslog(syslog.LOG_ERR, msg)


def exec_command(command, env=os.environ.copy(), shell=True):
	info("running: %s" % command)
	PIPE = subprocess.PIPE
	proc = subprocess.Popen(command, stdin=None, stdout=PIPE, stderr=PIPE, env=env, shell=shell)
	out,err = proc.communicate()
	info("returncode(%s)=%s" % (command, proc.returncode))
	info("stdout=%s" % out)
	info("stderr=%s" % err)
	return proc.returncode

def xpra_print(socket_dir, display, filename, mimetype, source, title, printer, no_copies, print_options):
	command = ["xpra", "--socket-dir=%s" % socket_dir, "print", display, filename, mimetype, source, title, printer, no_copies, print_options]
	#in this case, running as root cannot be avoided, so skip the warning:
	#(using "su" causes even more problems)
	env = os.environ.copy()
	env["XPRA_NO_ROOT_WARNING"] = "1"
	return exec_command(command, env=env, shell=False)


def do_main():
	info(" ".join(["'%s'" % x for x in sys.argv]))
	if len(sys.argv) == 1:
		# Without arguments should give backend info.
		# This is also used when lpinfo -v is issued, where it should include "direct this_backend"
		sys.stdout.write("direct %s \"Unknown\" \"Direct PDF Printing/Forwarding to host via xpra\"\n" % os.path.basename(sys.argv[0]))
		sys.stdout.flush()
		sys.exit(0)
	if len(sys.argv) not in (6,7):
		sys.stdout.write("Usage: %s job-id user title copies options [file]\n" % os.path.basename(sys.argv[0]))
		sys.stdout.flush()
		err("Wrong number of arguments. Usage: %s job-id user title copies options [file]" % sys.argv[0])
		sys.exit(1)
	job_id, username, title, no_copies, print_options = sys.argv[1:6]
	if len(sys.argv)==7:
		filename = sys.argv[6]
	else:
		filename = "-"
	info("username: %s, title: %s, filename: %s, job_id: %s" % (username, title, filename, job_id))

	dev_uri = os.environ['DEVICE_URI']
	parsed_url = urlparse.urlparse(dev_uri)
	info("urlparse(%s)=%s" % (dev_uri, parsed_url))
	#write_dir = parsed_url.path
	attributes = urlparse.parse_qs(parsed_url.query)
	info("attributes(%s)=%s" % (parsed_url.query, attributes))
	def aget(k, default_value):
		v =  attributes.get(k)
		if v is None:
			return default_value
		assert len(v)==1
		return v[0]
	display = aget("display", os.environ.get("DISPLAY"))
	socket_dir = aget("socket-dir", "/tmp")
	printer = aget("remote-printer", "")
	source = aget("source", "")
	if not source:
		raise Exception("Device URI: client source uuid is missing")
	if not display:
		raise Exception("Device URI: display number not specified!")
	info("xpra display: %s" % display)

	xpra_print(socket_dir, display, filename, "application/postscript", source, title, printer, no_copies, print_options)


def main():
	try:
		do_main()
	except Exception as e:
		err("failure in xpraforwarder main: %s" % e)
		for x in traceback.format_tb(sys.exc_info()[2]):
			err(x)


if __name__=='__main__':
	main()