Skip to content
This repository has been archived by the owner on Jan 5, 2024. It is now read-only.

Remove .ppd related logic and rely on CUPS to know how to print #94

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 1 addition & 9 deletions securedrop_export/export.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,15 +126,7 @@ def safe_check_call(self, command, error_message):
try:
subprocess.check_call(command)
except subprocess.CalledProcessError as ex:
# ppdc emits warnings which should not be treated as user facing errors
if (
ex.returncode == 0
and ex.stderr is not None
and ex.stderr.startswith("ppdc: Warning")
):
logger.info("Encountered warning: {}".format(ex.output))
else:
self.exit_gracefully(msg=error_message, e=ex.output)
self.exit_gracefully(msg=error_message, e=ex.output)


class ExportAction(abc.ABC):
Expand Down
44 changes: 2 additions & 42 deletions securedrop_export/print/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,6 @@

PRINTER_NAME = "sdw-printer"
PRINTER_WAIT_TIMEOUT = 60
BRLASER_DRIVER = "/usr/share/cups/drv/brlaser.drv"
BRLASER_PPD = "/usr/share/cups/model/br7030.ppd"
LASERJET_DRIVER = "/usr/share/cups/drv/hpcups.drv"
LASERJET_PPD = "/usr/share/cups/model/hp-laserjet_6l.ppd"

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -79,8 +75,7 @@ def check_printer_setup(self) -> None:
)

printer_uri = printers[0]
printer_ppd = self.install_printer_ppd(printer_uri)
self.setup_printer(printer_uri, printer_ppd)
self.setup_printer(printer_uri)
except subprocess.CalledProcessError as e:
logger.error(e)
self.submission.exit_gracefully(ExportStatus.ERROR_GENERIC.value)
Expand Down Expand Up @@ -114,40 +109,7 @@ def get_printer_uri(self):
logger.info("Printer {} is supported".format(printer_uri))
return printer_uri

def install_printer_ppd(self, uri):
if not any(x in uri for x in ("Brother", "LaserJet")):
logger.error(
"Cannot install printer ppd for unsupported printer: {}".format(uri)
)
self.submission.exit_gracefully(
msg=ExportStatus.ERROR_PRINTER_NOT_SUPPORTED.value
)
return

if "Brother" in uri:
printer_driver = BRLASER_DRIVER
printer_ppd = BRLASER_PPD
elif "LaserJet" in uri:
printer_driver = LASERJET_DRIVER
printer_ppd = LASERJET_PPD

# Compile and install drivers that are not already installed
if not os.path.exists(printer_ppd):
logger.info("Installing printer drivers")
self.submission.safe_check_call(
command=[
"sudo",
"ppdc",
printer_driver,
"-d",
"/usr/share/cups/model/",
],
error_message=ExportStatus.ERROR_PRINTER_DRIVER_UNAVAILABLE.value,
)

return printer_ppd

def setup_printer(self, printer_uri, printer_ppd):
def setup_printer(self, printer_uri):
# Add the printer using lpadmin
logger.info("Setting up printer {}".format(self.printer_name))
self.submission.safe_check_call(
Expand All @@ -159,8 +121,6 @@ def setup_printer(self, printer_uri, printer_ppd):
"-E",
"-v",
printer_uri,
"-P",
printer_ppd,
"-u",
"allow:user",
],
Expand Down
67 changes: 17 additions & 50 deletions tests/print/test_actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
SAMPLE_OUTPUT_NO_PRINTER = b"network beh\nnetwork https\nnetwork ipp\nnetwork ipps\nnetwork http\nnetwork\nnetwork ipp14\nnetwork lpd" # noqa
SAMPLE_OUTPUT_BROTHER_PRINTER = b"network beh\nnetwork https\nnetwork ipp\nnetwork ipps\nnetwork http\nnetwork\nnetwork ipp14\ndirect usb://Brother/HL-L2320D%20series?serial=A00000A000000\nnetwork lpd" # noqa
SAMPLE_OUTPUT_LASERJET_PRINTER = b"network beh\nnetwork https\nnetwork ipp\nnetwork ipps\nnetwork http\nnetwork\nnetwork ipp14\ndirect usb://HP/LaserJet%20Pro%20M404-M405?serial=A00000A000000\nnetwork lpd" # noqa
SAMPLE_OUTPUT_NOT_SUPPORTED_PRINTER = b"network beh\nnetwork https\nnetwork ipp\nnetwork ipps\nnetwork http\nnetwork\nnetwork ipp14\ndirect usb://Not/Supported?serial=A00000A000000\nnetwork lpd" # noqa
TEST_CONFIG = os.path.join(os.path.dirname(__file__), "sd-export-config.json")


Expand Down Expand Up @@ -50,6 +51,22 @@ def test_get_bad_printer_uri(mocked_call, capsys, mocker):
mocked_exit.assert_called_once_with(expected_message)


@mock.patch("subprocess.check_output", return_value=SAMPLE_OUTPUT_NOT_SUPPORTED_PRINTER)
def test_get_unsupported_printer_uri(mocked_call, capsys, mocker):
submission = export.SDExport("testfile", TEST_CONFIG)
action = PrintExportAction(submission)
expected_message = "ERROR_PRINTER_NOT_SUPPORTED"
assert export.ExportStatus.ERROR_PRINTER_NOT_SUPPORTED.value == expected_message
mocked_exit = mocker.patch.object(
submission, "exit_gracefully", side_effect=lambda x: sys.exit(0)
)

with pytest.raises(SystemExit):
action.get_printer_uri()

mocked_exit.assert_called_once_with(expected_message)


@pytest.mark.parametrize(
"open_office_paths",
[
Expand Down Expand Up @@ -80,55 +97,6 @@ def test_is_not_open_office_file(capsys, open_office_paths):
assert not action.is_open_office_file(open_office_paths)


@mock.patch("subprocess.check_call")
def test_install_printer_ppd_laserjet(mocker):
submission = export.SDExport("testfile", TEST_CONFIG)
action = PrintExportAction(submission)
ppd = action.install_printer_ppd(
"usb://HP/LaserJet%20Pro%20M404-M405?serial=A00000A00000"
)
assert ppd == "/usr/share/cups/model/hp-laserjet_6l.ppd"


@mock.patch("subprocess.check_call")
def test_install_printer_ppd_brother(mocker):
submission = export.SDExport("testfile", TEST_CONFIG)
action = PrintExportAction(submission)
ppd = action.install_printer_ppd(
"usb://Brother/HL-L2320D%20series?serial=A00000A000000"
)
assert ppd == "/usr/share/cups/model/br7030.ppd"


def test_install_printer_ppd_error_no_driver(mocker):
submission = export.SDExport("testfile", TEST_CONFIG)
action = PrintExportAction(submission)
mocked_exit = mocker.patch.object(submission, "exit_gracefully", return_value=0)
mocker.patch(
"subprocess.check_call", side_effect=CalledProcessError(1, "check_call")
)

action.install_printer_ppd(
"usb://HP/LaserJet%20Pro%20M404-M405?serial=A00000A000000"
)

assert mocked_exit.mock_calls[0][2]["msg"] == "ERROR_PRINTER_DRIVER_UNAVAILABLE"
assert mocked_exit.mock_calls[0][2]["e"] is None


def test_install_printer_ppd_error_not_supported(mocker):
submission = export.SDExport("testfile", TEST_CONFIG)
action = PrintExportAction(submission)
mocked_exit = mocker.patch.object(submission, "exit_gracefully", return_value=0)
mocker.patch(
"subprocess.check_call", side_effect=CalledProcessError(1, "check_call")
)

action.install_printer_ppd("usb://Not/Supported?serial=A00000A000000")

assert mocked_exit.mock_calls[0][2]["msg"] == "ERROR_PRINTER_NOT_SUPPORTED"


def test_setup_printer_error(mocker):
submission = export.SDExport("testfile", TEST_CONFIG)
action = PrintExportAction(submission)
Expand All @@ -139,7 +107,6 @@ def test_setup_printer_error(mocker):

action.setup_printer(
"usb://Brother/HL-L2320D%20series?serial=A00000A000000",
"/usr/share/cups/model/br7030.ppd",
)

assert mocked_exit.mock_calls[0][2]["msg"] == "ERROR_PRINTER_INSTALL"
Expand Down