如何对 CUPS 打印机/打印作业进行逆向工程?

如何对 CUPS 打印机/打印作业进行逆向工程?

我在本地 PDF 打印 (CUPS) 与 Google 云打印之间存在质量问题。 (GCP 更好,使用 CUPS 我会得到错误的大小、错误的字符、错误的字体。所以我想知道 CUPS 是做什么的!)

打印机本身可以处理多种格式:application/pdf (≥ 1.0, ≤ 1.7)、image/jpeg、image/tiff、image/pwg-raster

几个月来,我以不同的方式将打印机添加到 CUPS,我还使用它“无驱动”,其中 CUPS 检测本地网络本身中的打印机。

在所有情况下,打印 PDF 时都会出现错误;不完全是这样,但印刷品对我来说毫无用处。发生了什么:页面放大了约 30%,从第 2 或第 3 页开始,字体混合在一起,字符变成符号,段落以粗体打印,等等......

如果在同一台打印机上通过 Google 云打印打印相同的 PDF,效果会非常好。直接将 PDF 发送至 USB 记忆棒打印机也同样很棒。 – 我希望从我的计算机打印得到同样好的结果!

我的问题是:

  • 我想知道每台 CUPS 打印机在发送到真正的打印机之前在我的机器上采用什么管道。它检测格式吗?如何?它会再次重新转换为 PDF 吗?它将使用哪种 PPD?管道还采取哪些其他决策以及进行哪些转换?
  • 我想从已通过的打印作业中了解:CUPS 检测到了什么?它做了哪些转换?我在哪里可以获取生成的中间输出?

到目前为止,我没有发现 CUPS 调试/逆向工程的良好切入点(使用我的心中的疑问)...

答案1

我只回答你的部分问题,因为你似乎拥有敏锐的头脑,只需要展示一些隐藏的钩子就可以爬上墙壁:

  1. “它将使用哪种 PPD?”

    如果一个打印队列printername是本地安装的(如果它不是“原始”队列),它将使用 PPD/etc/cups/ppd/printername.ppd

  2. “它能检测格式吗?如何检测?”

    是的,它确实。当您启用调试日志记录时(行LogLevel debug/etc/cups/cupsd.conf),你会看到一行错误日志阅读“自动输入文件……”。 (如果作业已经声明了哑剧类型,则不会自动键入,例如lp -d printername -o document-format=application/pdf my.pdf.)

    各种 MIME 类型的分类规则定义在/usr/share/cups/mime.types以及可能与后缀位于同一目录中的所有其他文件*.类型。 (您也可以在那里放置您自己的规则,以定义您自己的自定义 MIME 类型,这些类型应由您自己的自定义过滤器处理......)

  3. “管道还做出哪些其他决定以及进行哪些转换?”

    1. 如果 PPD 没有任何以其中之一开头的行*cupsFilter:或者cupsFilter2:关键字,则假定最终打印设备是 PostScript 打印机。因此,它将所有内容转换为 PostScript,而不会作为 PostScript 提交。

    2. 如果有一行或多行以关键字开头*cupsFilter:或者*cupsFilter2:它将从这些行中读取打印设备可以使用的 MIME 类型,并将采用适当的过滤器链来生成相应的 MIME 类型。

    3. 可以处理某些 MIME 类型的过滤器列于/usr/share/cups/mime.convs以及可能与后缀位于同一目录中的所有其他文件*.转换。 (您可以将自己的自定义过滤器放在那里,用于您想要由这些过滤器处理的任何 MIME 类型...)

    4. *.转换文件命名了相应过滤器可以使用和生成的输入和输出 MIME 类型,以及这种转换将导致的虚拟“成本”(只是一个整数)。当面对 CUPS 可以构建的不同可能的过滤链时,它会application/alpha选择application/zeta总成本最低的一个。

  4. “它会再次重新转换为 PDF 吗?”

    很可能不会。除非您要求将打印选项用于需要它的原始 PDF:仅打印一系列页面;在一张纸上打印 2 页或更多页;缩放它;重新排列页面以进行小册子打印等。然后pdftopdf可以应用过滤器,将其转换为application/pdfapplication/vnd.cups-pdf

  5. “CUPS 检测到了什么?”

    参见上文:在中搜索字符串“自动键入文件”/var/log/error_log:

    sudo grep -A 2 "Auto-typing file" /var/log/error_log
    
  6. “它做了什么转换?”

    参见error_log再次并搜索包含的行Started filter:

    sudo grep "Started filter" /var/log/error_log
    
  7. “我在哪里可以获取生成的中间输出?”

    您不能直接执行此操作。您必须操作 CUPS 的每个过滤器才能写出中间格式。 (我去做吧,我有一个现成的食谱,但你必须付钱给我才能应用它。)

    因此,获取中间输出可能超出了您的范围,您可以做一些不同的事情:模拟过滤链CUPS 会雇用任何工作。

    您可以通过阅读手册页来了解如何执行此操作cupsfilter。您还可以仅列出 CUPS 将用于任何打印队列的过滤器:

    cupsfilter           \
        --list-filters    \
        -d <printername>   \
        -i <inputmime/type> \
        -m <outputmime/type> \
        -o "number-up=4 page-ranges=3-5,7,11" \
         <filename>
    

答案2

您的问题没有指定您正在使用的操作系统。我的答案是针对 Debian 9.6 和网络连接的 Kyocera FS-1350DN,指定用于处理“PDF 直接打印”。那里应该cups 没有必要篡改 PDF 文件。

要找到答案,您必须启用 cups 调试。不幸的是,cupsctl --debug-logging(作为 root)失败并出现错误消息cupsctl: Forbidden。在文件 /etc/cups/cupsd.conf 中设置LogLevel debug并重新启动 cupsd 后,我发送了一个带有lpr scale.pdf.该文件包含来自 CAD 程序的线条图形(无灰度)并以 100% 比例打印。

/var/log/cups/error_log 中的相关行(总共 300 行)如下:


D [11/Dec/2018:17:50:02 +0100] [Job 319] Request file type is application/pdf.
D [11/Dec/2018:17:50:02 +0100] [Job 319] 3 filters for job:
D [11/Dec/2018:17:50:02 +0100] [Job 319] pdftopdf (application/pdf to application/vnd.cups-pdf, cost 66)
D [11/Dec/2018:17:50:02 +0100] [Job 319] pdftops (application/vnd.cups-pdf to application/vnd.cups-postscript, cost 100)
D [11/Dec/2018:17:50:02 +0100] [Job 319] - (application/vnd.cups-postscript to printer/fs1350, cost 0)
I [11/Dec/2018:17:50:02 +0100] [Job 319] Started filter /usr/lib/cups/filter/pdftopdf (PID 16570)
I [11/Dec/2018:17:50:02 +0100] [Job 319] Started filter /usr/lib/cups/filter/pdftops (PID 16571)
I [11/Dec/2018:17:50:02 +0100] [Job 319] Started backend /usr/lib/cups/backend/socket (PID 16572)
D [11/Dec/2018:17:50:02 +0100] [Job 319] pdftops - copying to temp print file \"/tmp/040bb5c158ce7\"
D [11/Dec/2018:17:50:02 +0100] [Job 319] PID 16570 (/usr/lib/cups/filter/pdftopdf) exited with no errors.
D [11/Dec/2018:17:50:02 +0100] [Job 319] 319 h scale.pdf 1 \'finishings=3 job-uuid=urn:uuid:045216b6-e2e0-34ee-50af-36c3bdbdc04f job-originating-host-name=192.168.0.2 date-time-at-creation= date-time-at-processing= time-at-creation=1544547002 time-at-processing=1544547002 document-name-supplied=scale.pdf\'
D [11/Dec/2018:17:50:02 +0100] [Job 319] Running command line for gs: gs -q -dNOPAUSE -dBATCH -dSAFER -dNOMEDIAATTRS -sDEVICE=ps2write -sOUTPUTFILE=%stdout -dLanguageLevel=3 -r1200 -dCompressPages=false -dCompressFonts=false -dNoT3CCITT -dNOINTERPOLATE -c \'save pop\' -f /tmp/040bb5c158ce7
D [11/Dec/2018:17:50:02 +0100] [Job 319] Started filter gs (PID 16577)
D [11/Dec/2018:17:50:02 +0100] [Job 319] Started post-processing (PID 16578)
D [11/Dec/2018:17:50:02 +0100] [Job 319] Started filter pstops (PID 16579)
D [11/Dec/2018:17:50:02 +0100] [Job 319] %!PS-Adobe-3.0
D [11/Dec/2018:17:50:02 +0100] [Job 319] %%BoundingBox: 0 0 595 842
D [11/Dec/2018:17:50:02 +0100] [Job 319] %%HiResBoundingBox: 0 0 595.00 842.00
D [11/Dec/2018:17:50:02 +0100] [Job 319] %%Creator: GPL Ghostscript 920 (ps2write)
D [11/Dec/2018:17:50:02 +0100] [Job 319] %%LanguageLevel: 2
D [11/Dec/2018:17:50:02 +0100] [Job 319] %%CreationDate: D:20181211175002+01\'00\'
D [11/Dec/2018:17:50:02 +0100] [Job 319] %%Pages: 1
D [11/Dec/2018:17:50:02 +0100] [Job 319] %%EndComments
D [11/Dec/2018:17:50:02 +0100] [Job 319] PID 16577 (gs) exited with no errors.
D [11/Dec/2018:17:50:02 +0100] [Job 319] PID 16578 (Post-processing) exited with no errors.
D [11/Dec/2018:17:50:02 +0100] [Job 319] PID 16579 (pstops) exited with no errors.
D [11/Dec/2018:17:50:02 +0100] [Job 319] PID 16571 (/usr/lib/cups/filter/pdftops) exited with no errors.

包含的行- (application/vnd.cups-postscript to printer/fs1350, cost 0)告诉您cups正在使用后处理器(也称为打印机驱动程序)/etc/cups/ppd/fs1350.ppd。使用 - 命令可以获得同一进程的另一个视图ps。一个摘抄的输出

while true ; do date +'%N'>> log; ps axSfu | fgrep -v grep | egrep '^lp[[:space:]]|/usr/sbin/cupsd' >> log ; done

这是


root     15796  0.1  0.1 171440  8536 ?        Ssl  17:49   0:00 /usr/sbin/cupsd -l
lp       16571  0.0  0.0  77632  5728 ?        S    17:50   0:00  \_ fs1350 319 h scale.pdf 1 finishings=3 number-up=1 job-uuid=urn:uuid:045216b6-e2e0-34ee-50af-36c3bdbdc04f job-originating-host-name=192.168.0.2 date-time-at-creation= date-time-at-processing= time-at-creation=1544547002 time-at-processing=1544547002 document-name-supplied=scale.pdf
lp       16577  0.0  0.2 129760 20836 ?        R    17:50   0:00  |   \_ gs -q -dNOPAUSE -dBATCH -dSAFER -dNOMEDIAATTRS -sDEVICE=ps2write -sOUTPUTFILE=%stdout -dLanguageLevel=3 -r1200 -dCompressPages=false -dCompressFonts=false -dNoT3CCITT -dNOINTERPOLATE -c save pop -f /tmp/040bb5c158ce7
lp       16578  0.0  0.0  77632   924 ?        S    17:50   0:00  |   \_ fs1350 319 h scale.pdf 1 finishings=3 number-up=1 job-uuid=urn:uuid:045216b6-e2e0-34ee-50af-36c3bdbdc04f job-originating-host-name=192.168.0.2 date-time-at-creation= date-time-at-processing= time-at-creation=1544547002 time-at-processing=1544547002 document-name-supplied=scale.pdf
lp       16579  0.0  0.0  75424  5288 ?        S    17:50   0:00  |   \_ fs1350 319 h scale.pdf 1 finishings=3 job-uuid=urn:uuid:045216b6-e2e0-34ee-50af-36c3bdbdc04f job-originating-host-name=192.168.0.2 date-time-at-creation= date-time-at-processing= time-at-creation=1544547002 time-at-processing=1544547002 document-name-supplied=scale.pdf
lp       16572  0.0  0.0  79792  5900 ?        S    17:50   0:00  \_ socket://fs1350.xxxx.xxxx.xxx 319 h scale.pdf 1 finishings=3 number-up=1 job-uuid=urn:uuid:045216b6-e2e0-34ee-50af-36c3bdbdc04f job-originating-host-name=192.168.0.2 date-time-at-creation= date-time-at-processing= time-at-creation=1544547002 time-at-processing=1544547002 document-name-supplied=scale.pdf

告诉我们cups调用预过滤器(pdftops,PID 16571,此处名为 fs1350)和后端(PID 16572,此处名为 socket://fs1350.xxxx.xxxx.xxx)。预过滤器调用gs.由于整个处理时间不到 0.2 秒,因此将输出收集到文件中是有意义的。只是date +'%N'为了了解时间安排。

明显的不必要的缩放(我在评论中写到)是evince→Print→Print Setup→Scale→100%因为默默地被覆盖经过evince→Print→Page Handling→Fit to Printable Area。因此,请务必仔细检查您的打印客户。

唉,这还不是故事的全部。为了绕过cups并使用打印机的“PDF直接打印”功能,我直接发送了文件:nc fs1350.xxxx.xxxx.xxx 9100 < scale.pdf.经过 10 多分钟的处理时间后,打印机将纸张发出。

使用 netcat 进行原始打印

使用 netcat 进行原始打印,数字反映尺寸(以毫米为单位)。

使用 lpr→cups 打印输出

使用 lpr→cups 打印输出

以 1200 dpi 渲染的文件的位图图像

文件的位图图像 (1200 dpi)

无论打印机设置如何“覆盖 A4/LT”,原始打印的缩放比例均为 97.7%,而 lpr→cups 打印的缩放比例则正常。原始打印的网点增大较小,而 lpr→cups 打印的网点增大则有点微薄。

缩小之前绘图的页面尺寸生的印刷扩大了规模。

答案3

让我在这里补充一下...我正在运行带有 CUPS 2.3.3op2 的 Gentoo Linux,通过 IPP Everywhere 将作业发送到 Xerox VersaLink C405。该打印机本身支持 PostScript(真正的 Adob​​e PostScript 3,而不是仿真)以及 PDF、PCL6、PCL5e 和 XPS。

从日志中的调试信息来看,CUPS 正在将 PostScript 发送到机器,无论输入格式如何。这是我在将 PDF 数据通过管道传输到时看到的情况lp(为了可读性而删除了日期):

[Job 61] 3 filters for job:
[Job 61] pdftopdf (application/pdf to application/vnd.cups-pdf, cost 66)
[Job 61] pdftops (application/vnd.cups-pdf to application/vnd.cups-postscript, cost 100)
[Job 61] - (application/vnd.cups-postscript to printer/vlc405, cost 0)

如果您想将 PDF 直接发送到打印机,您可以完全绕过 CUPS,并使用 netcat 将数据直接发送到打印机上的端口 9100(假设已启用):

nc 192.0.2.0 9100 < file.pdf

(将 IP 地址替换为您的打印机的 IP 地址。)

如果您的机器不直接支持 PostScript 或 PDF,则此方法不适用。正版 Adob​​e PostScript 3 支持通常仅限于办公用途的高端激光打印机。消费级打印机可能会使用 PWG Raster 或 PDF 来实现 IPP Everywhere。有些模仿了 PostScript 3,这可能不太可靠。 (经常使用仿真,因为 Adob​​e 参考实现的许可费用昂贵。)

相关内容