Add custom QZ Tray fork with pairing key authentication

- Custom fork of QZ Tray 2.2.x with certificate validation bypassed
- Implemented pairing key (HMAC) authentication as replacement
- Modified files: PrintSocketClient.java (certificate check disabled)
- New files: PairingAuth.java, PairingConfigDialog.java
- Excluded build artifacts (out/, lib/javafx*) from repository
- Library JARs included for dependency management
This commit is contained in:
2025-10-02 02:27:45 +03:00
parent 755400a269
commit c7266c32ee
444 changed files with 63195 additions and 1 deletions

View File

@@ -0,0 +1,242 @@
/**
* @author Tres Finocchiaro
*
* Copyright (C) 2016 Tres Finocchiaro, QZ Industries, LLC
*
* LGPL 2.1 This is free software. This software and source code are released under
* the "LGPL 2.1 License". A copy of this license should be distributed with
* this software. http://www.gnu.org/licenses/lgpl-2.1.html
*/
package qz.printer;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import qz.printer.info.CachedPrintServiceLookup;
import qz.printer.info.NativePrinter;
import qz.printer.info.NativePrinterMap;
import qz.utils.SystemUtilities;
import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import javax.print.attribute.ResolutionSyntax;
import javax.print.attribute.standard.*;
import java.util.*;
public class PrintServiceMatcher {
private static final Logger log = LogManager.getLogger(PrintServiceMatcher.class);
// PrintService is slow in CUPS, use a cache instead per JDK-7001133
// TODO: Include JDK version test for caching when JDK-7001133 is fixed upstream
private static final boolean useCache = SystemUtilities.isUnix();
public static NativePrinterMap getNativePrinterList(boolean silent, boolean withAttributes) {
NativePrinterMap printers = NativePrinterMap.getInstance();
printers.putAll(true, lookupPrintServices());
if (withAttributes) { printers.values().forEach(NativePrinter::getDriverAttributes); }
if (!silent) { log.debug("Found {} printers", printers.size()); }
return printers;
}
private static PrintService[] lookupPrintServices() {
return useCache ? CachedPrintServiceLookup.lookupPrintServices() :
PrintServiceLookup.lookupPrintServices(null, null);
}
private static PrintService lookupDefaultPrintService() {
return useCache ? CachedPrintServiceLookup.lookupDefaultPrintService() :
PrintServiceLookup.lookupDefaultPrintService();
}
public static NativePrinterMap getNativePrinterList(boolean silent) {
return getNativePrinterList(silent, false);
}
public static NativePrinterMap getNativePrinterList() {
return getNativePrinterList(false);
}
public static NativePrinter getDefaultPrinter() {
PrintService defaultService = lookupDefaultPrintService();
if(defaultService == null) {
return null;
}
NativePrinterMap printers = NativePrinterMap.getInstance();
if (!printers.contains(defaultService)) {
printers.putAll(false, defaultService);
}
return printers.get(defaultService);
}
public static String findPrinterName(String query) throws JSONException {
NativePrinter printer = PrintServiceMatcher.matchPrinter(query);
if (printer != null) {
return printer.getPrintService().value().getName();
} else {
return null;
}
}
/**
* Finds {@code PrintService} by looking at any matches to {@code printerSearch}.
*
* @param printerSearch Search query to compare against service names.
*/
public static NativePrinter matchPrinter(String printerSearch, boolean silent) {
NativePrinter exact = null;
NativePrinter begins = null;
NativePrinter partial = null;
if (!silent) { log.debug("Searching for PrintService matching {}", printerSearch); }
// Fix for https://github.com/qzind/tray/issues/931
// This is more than an optimization, removal will lead to a regression
NativePrinter defaultPrinter = getDefaultPrinter();
if (defaultPrinter != null && printerSearch.equals(defaultPrinter.getName())) {
if (!silent) { log.debug("Matched default printer, skipping further search"); }
return defaultPrinter;
}
printerSearch = printerSearch.toLowerCase(Locale.ENGLISH);
// Search services for matches
for(NativePrinter printer : getNativePrinterList(silent).values()) {
if (printer.getName() == null) {
continue;
}
String printerName = printer.getName().toLowerCase(Locale.ENGLISH);
if (printerName.equals(printerSearch)) {
exact = printer;
break;
}
if (printerName.startsWith(printerSearch)) {
begins = printer;
continue;
}
if (printerName.contains(printerSearch)) {
partial = printer;
continue;
}
if (SystemUtilities.isMac()) {
// 1.9 compat: fallback for old style names
PrinterName name = printer.getLegacyName();
if (name == null || name.getValue() == null) { continue; }
printerName = name.getValue().toLowerCase(Locale.ENGLISH);
if (printerName.equals(printerSearch)) {
exact = printer;
continue;
}
if (printerName.startsWith(printerSearch)) {
begins = printer;
continue;
}
if (printerName.contains(printerSearch)) {
partial = printer;
}
}
}
// Return closest match
NativePrinter use = null;
if (exact != null) {
use = exact;
} else if (begins != null) {
use = begins;
} else if (partial != null) {
use = partial;
}
if (use != null) {
if(!silent) log.debug("Found match: {}", use.getPrintService().value().getName());
} else {
log.warn("Printer not found: {}", printerSearch);
}
return use;
}
public static NativePrinter matchPrinter(String printerSearch) {
return matchPrinter(printerSearch, false);
}
public static JSONArray getPrintersJSON(boolean includeDetails) throws JSONException {
JSONArray list = new JSONArray();
PrintService defaultService = lookupDefaultPrintService();
boolean mediaTrayCrawled = false;
for(NativePrinter printer : getNativePrinterList().values()) {
PrintService ps = printer.getPrintService().value();
JSONObject jsonService = new JSONObject();
jsonService.put("name", ps.getName());
if (includeDetails) {
jsonService.put("driver", printer.getDriver().value());
jsonService.put("connection", printer.getConnection());
jsonService.put("default", ps == defaultService);
if (!mediaTrayCrawled) {
log.info("Gathering printer MediaTray information...");
mediaTrayCrawled = true;
}
HashSet<String> uniqueSizes = new HashSet<>(); // prevents duplicates
JSONArray trays = new JSONArray();
JSONArray sizes = new JSONArray();
for(Media m : (Media[])ps.getSupportedAttributeValues(Media.class, null, null)) {
if (m instanceof MediaTray) { trays.put(m.toString()); }
if (m instanceof MediaSizeName) {
if(uniqueSizes.add(m.toString())) {
MediaSize mediaSize = MediaSize.getMediaSizeForName((MediaSizeName)m);
if(mediaSize == null) {
continue;
}
JSONObject size = new JSONObject();
size.put("name", m.toString());
JSONObject in = new JSONObject();
in.put("width", mediaSize.getX(MediaPrintableArea.INCH));
in.put("height", mediaSize.getY(MediaPrintableArea.INCH));
size.put("in", in);
JSONObject mm = new JSONObject();
mm.put("width", mediaSize.getX(MediaPrintableArea.MM));
mm.put("height", mediaSize.getY(MediaPrintableArea.MM));
size.put("mm", mm);
sizes.put(size);
}
}
}
if(trays.length() > 0) {
jsonService.put("trays", trays);
}
if(sizes.length() > 0) {
jsonService.put("sizes", sizes);
}
PrinterResolution res = printer.getResolution().value();
int density = -1; if (res != null) { density = res.getFeedResolution(ResolutionSyntax.DPI); }
jsonService.put("density", density);
}
list.put(jsonService);
}
return list;
}
}