Skip to content

Substitutions

Tres Finocchiaro edited this page Jun 25, 2024 · 24 revisions

Compatibility

  • ✅ 2.2 | ⛔ 2.1 | ⛔ 2.0 | ⛔ 1.9 | ...

Contents

Since QZ Tray 2.2.4, clients have the ability to make advanced client-side overrides to the JSON websocket data. This low-level control for clients is in direct response to lack of flexibility by website developers.

For resiliency, the JSON substitution is limited only to trivial traits of a print job, such as page size and printer name, although this behavior can be altered slightly by loosening the security of certain restricted keywords.

Usage

Basic Usage

Basic usage is as follows:

  1. Create a file called substitutions.json

  2. Use the keywords use and for to instruct QZ how to perform JSON substitution replace and search, respectively.

    [
      {
        "use": {
          "config": {"size": {"width": "100", "height": "150"}, "units": "mm"}
        },
        "for": {
          "config": {"size": {"width": "4", "height": "6"}}
        }
      }
    ]
  3. Drag and drop the file into the About dialog (QZ Menu -> About)
    Screenshot 2024-04-24 at 5 24 14 PM

    • Alternately, you may copy this file to <SHARED_DIR>/substitutions.json (QZ Tray -> Advanced -> Diagnostics -> Browse Shared Folder) and restart QZ Tray.
  4. Submit a print job and check the logs to confirm (QZ Menu -> Advanced -> Diagnostics -> View Logs)

    [DEBUG] 2024-04-24T14:26:42,669 @ qz.ws.substitutions.Substitutions:76
    +    Matched JSON substitution rule: for: {"params":{"options":{"size":{"width":"4","height":"6"}}}}, use: {"params":{"options":{"size":{"width":"100","height":"150"},"units":"mm"}}}
  5. The above example substitutes all print commands for the paper size 4x6 (in) to 100x150 (mm).

Printer Substitution

To instruct QZ Tray to send a print job to a different printer, use the "printer": { ... } directive:

[
  {
    "use": {
       "printer": "XPS Document Writer"
    },
    "for": {
       "printer": "PDFwriter"
    }
  }
]
[DEBUG] 2024-04-24T14:26:42,672 @ qz.ws.substitutions.Substitutions:76
+    Matched JSON substitution rule: for: {"params":{"printer":{"name":"PDFwriter"}}}, use: {"params":{"printer":{"name":"XPS Document Writer"}}}
Printer Search

To replace a printer name while searching, use the "query": keyword instead. The two techniques may also be combined.

[
  {
    "use": {
       "query": "XPS Document Writer"
    },
    "for": {
       "query": "PDFwriter"
    }
  }
]

Size Substitution

  • The most common reason for JSON substitutions is the unwillness of website providers to modify their application for custom paper sizes. Although justifications for this are generally warranted (e.g. strict shipping regulations), the resulting impact to the end-users can be crippling.

    US Letter vs. A4
    [
      {
        "use": { "config": {"size": {"width": 210, "height": 297}, "units": "mm"} },
        "for": { "config": {"size": {"width": 8.5, "height": 11}, "units": "in"} }
      }
    ]
    Rollo
    [
      {
        "use": { "config": {"size": {"width": 100, "height": 150}, "units": "mm"} },
        "for": { "config": {"size": {"width": 4, "height": 6}, "units": "in"} }
      }
    ]
    Brother DK-1247
    [
      {
        "use": { "config": {"size": {"width": 4.08, "height": 6.47}, "units": "in"} },
        "for": { "config": {"size": {"width": 4, "height": 6}, "units": "in"} }
      }
    ]

Restricted Keywords

  • By default, certain keywords cannot be modified such as "copies": or nested "data": { "data": ... } elements. This is to ensure that the content and quantity being printed matches that intended by the website.

  • This behavior can be disabled by setting property security.substitutions.strict to false.

    Restrict (true)
    [WARN] 2024-04-24T14:26:42,672 @ qz.ws.substitutions.Substitutions:132
    -    Use of { "options": { "copies": ... } } is restricted, removing
    [WARN] 2024-04-24T14:26:42,672 @ qz.ws.substitutions.Substitutions:148
    -    Use of { "data": { "data": ... } } is restricted, removing
    Restrict (false)
    [DEBUG] 2024-04-25T13:27:23,844 @ qz.ws.substitutions.Substitutions:79
    +    Matched JSON substitution rule: for: {"params":{"options":{"copies":1}}}, use: {"params":{"options":{"copies":3}}}
    [DEBUG] 2024-04-25T13:27:23,844 @ qz.ws.substitutions.Substitutions:79
    +    Matched JSON substitution rule: for: {"params":{"data":[{"data":"https://google.com"}]}}, use: {"params":{"data":[{"data":"https://yahoo.com"}]}}
  • Justification for these default restrictions:

    • Due to the wide adoption of QZ Tray for strictly monitored items such as ticket sales, "copies": ... is considered to be a risk and is disabled by default.
    • Modifying data blobs (such as URLs, base64, raw content), materially changes the print job and would otherwise defeat the purpose of digitally signing the content.

Sanitization

  • For convenience and consistency with the api, keywords such as config, printer, data, are offered over their verbatim JSON counterparts (See table).

  • To make the JSON slightly more human-readable/human-writable, implied arrays such as data will be automatically converted to an array before matching (See table).

  • If desired, the sanitized/expanded versions may be used verbatim instead.

    keyword sanitized/expanded
    "printer": ... "params": {"printer": {"name": ... } }
    "query": ... "params": {"query": ... }
    "config": ... "params": {"options": ... }
    "data": {"options": ... } "params": {"data": [ { "options": ... } ] }

Advanced

Disable Subtitutions
  • Substitutions are enabled by default for all QZ Tray installations. If needed, this feature can be disabled by setting property security.substitutions.enable to false.
Case-Sensitivity
  • Case-sensitive searching can be configured by setting the property "for": { "caseSensitive": true }. By default all searches will ignore case when comparing.

    [
      {
        "use": {
          "printer": "PDFwriter"
        },
        "for": {
          "caseSensitive": true,
          "printer": "XPS Document Writer"
        }
      }
    ]
Clone this wiki locally